• java知识回顾笔记(对象、反射、内省、实例、父类、构造方法、封装、泛型、super())


    类&对象

    在创建了一个类时,只声明但不赋值,其默认值为:
    在这里插入图片描述
    理解下图含义,即可理解对象和类:

    在这里插入图片描述

    实例

    对象又被称为实例,实例变量被创建时,系统默认会赋值,例如:

    Student student = new Student()
    # student.name此时就有默认值
    
    • 1
    • 2

    堆和栈

    对象是存在堆内存中的,方法所需要的内存会在栈中分配,例如main()方法。
    1.堆内存中存储对象以及实例变量
    2.局部变量存放在栈里面
    3.当new 一个对象时,例如Student s1=new Student()时(s1为局部变量),s1此时存储的为对象的堆地址,像s1这种存储了地址的变量有一个特殊的名字:引用
    在这里插入图片描述
    在这里插入图片描述

    java执行堆栈画图【老杜版】

    局部变量&成员变量

    方法体外(class里)的变量叫成员变量、方法体内声明的变量叫局部变量
    局部变量存放在栈内存中,成员变量也叫实例变量存放在堆内存
    在这里插入图片描述

    构造方法

    构造方法又被称为:构造器、Constructor、构造函数
    构造方法有两个作用:1.创建对象 2.给对象赋值

    当new一个对象时,会自动运行一个无参数的构造方法,当用户没有自定义一个构造方法时,系统默认提供了一个无参数的构造方法

    public class test {
        public static void main(String[] args){
            Student student = new Student();
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Student.java

    public class Student {
    	String name;
        public Student(){
            System.out.println("execute!!!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    知识回顾

    封装

    封装就是将public私有化

    封装的主要作用:
    1.保证内部结构安全
    2.屏蔽复杂、暴露简单

    方法名解析static

    在方法体中声明的变量叫做局部变量
    在方法体外声明的变量叫做成员变量
    成员变量又分为:实例变量、静态变量,例如:

    class VarTest{
    //成员变量中的实例变量,可以new对象,所以会造成空指针异常
    int i;
    //成员变量中的静态变量,静态的,不会需要new对象,不会造成空指针异常
    static int k;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    静态方法:

    public static void m1(){
    }
    
    • 1
    • 2

    那么我们什么时候使用static,什么时候不使用呢?根据上面提到的,成员变量中不使用static就是实例变量:

    Class Chinese{
    //身份证应该是实例变量,因为一个身份证对应一个对象
    String idCard;
    //国籍,国籍是一个类别人的特性,并不属与一个人的特性
    //String Contry;
    Static String Contry;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果使用非static修饰,contry每次都会在内存中开拓一片空间,导致内存浪费
    在这里插入图片描述
    如果使用static修饰,contry会存放在方法区中,不会被新建到对象中
    在这里插入图片描述
    我们可以通过Chinese.Contry来实现调用Contry,但是不能直接调用Chinese.idCard。因为Contry是被static修饰的静态变量,被static修饰的内容都可以采用类名.进行访问

    Class Chinese{
    //身份证应该是实例变量,因为一个身份证对应一个对象
    String idCard;
    //国籍,国籍是一个类别人的特性,并不属与一个人的特性
    //String Contry;
    Static String Contry = "中国";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    static: 都是修饰类相关的,所有static修饰的都可以采用类名.进行访问

    反射

    反射包:java.lang.refiect.*

    java.lang核心包
    java.util工具包
    java.io io流包

    反射的标志:

    Class c1 = Class.forName("java.lang.String")  //c1代表了String.class文件,或者说代表了String类型
    
    • 1

    反射可以操作class文件,反射机制相关重要的类有:

    java.lang.Class:代表整个字节码,代表一个类型
    java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。
    java.lang.reflect.Constructor:代表字节码中的构造方法字节码
    java.lang.reflect.Field:代表字节码中的属性字节码
    要先调用了Class,才能获得Method、Constructor、Field等

    要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取到java.lang.Class实例?:

    第一种:Class c = Class.forName(“完整类名带包名”);
    第二种:Class c = 对象.getClass();
    第三种:Class z =String.class; Class k =Data.class;

    代码分析:
    以下就是通过反射配合newInstance创建对象,c此时代表User.class这个文件或者说代表了这个类型

    Class. c = Class.forName("com.test.java.bean.User");
    Object obj = c.newInstance();
    
    • 1
    • 2

    举例,通过反射调用runtime.exec弹计算器:

    invoke是Method类中的一个方法。表示执行方法的调用
    参数1.表示一个对象,要执行这个对象的方法
    参数2.方法执行的参数

    Runtime r = Runtime.getRuntime();
    Class run = Runtime.getRuntime().getClass();
    // 获取Runtime的exec方法
    Method execMethod = run.getMethod("exec",String.class);
    // 调用exec方法
    execMethod.invoke(r,"calc");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通过反射给属性值赋值

    Class c = Class.forName("com.java.test.Student"); 
    Object obj = c.newInstance();
    Field noFiled = c.getDeclaredField("password") //Student类中有一个String password;
    noFiled.set(obj,2222)//给password设置值为2222
    noFiled.get(obj)//读取password的值
    
    //私有变量可以通过以下代码进行打破封装进行访问
    noFiled.setAccessible(true)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    通过反射调用指定参数类型的构造方法

    Map map = TransformedMap.decorate(map, null, d);
    Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    //AnnotationInvocationHandler类中有一个构造方法只接收(Class.class,Map.class)传入
    Constructor ct = cls.getDeclaredConstructor(Class.class,Map.class);
    ct.setAccessible(true);
    //创建对象
    Object o = ct.newInstance(Documented.class, map);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    泛型

    在下面这种情况时,it.next()该用哪种类型去接收?
    在这里插入图片描述
    使用泛型指定list中只能存储Animal类型的数据

    list<Animal> myList = new ArrayList<Animal>();
    
    • 1

    因为Cat和Bird都是继承Animal的,所以这时候能够:

    Cat c = new Cat();
    Bird b = new Bird();
    myList.add(c);
    myList.add(b);
    
    Iterator<Animal> it =myList.iterator();
    while(it.hasNext()){
    	Animal a = it.next();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    super()

    当一个构造方法,存在super(),代表调用父类的无参构造方法,当存在super(123)表示调用父类有参数的构造方法:

    class B extends A{
    	super();
    	super(123);
    	public B(){
    		System.out.println("B类无参构造方法!")
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    匿名内部类+回调编程写法

    回调编程: 通俗理解,callInContext方法内部定义了对.call的调用(接收一个Object参数,calllnContext内部实现调用了Object.call),而传入的对象类型ContextualCallable并且实现了call方法
    匿名内部类: 即ContextualCallable只是一个接口,它没有显式的类名,而是在创建对象的同时定义和实现类。

    public <T> T getInstance(final Class<T> type) {
        return this.callInContext(new ContextualCallable<T>() {
            public T call(InternalContext context) {
                return ContainerImpl.this.getInstance(type, context);
            }
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    匿名内部类例子1:

    public interface Greeting {
        void sayHello();
    }
    public class Main {
        public static void main(String[] args) {
            // 使用匿名内部类实现接口
            Greeting greeting = new Greeting() {
                public void sayHello() {
                    System.out.println("Hello, world!");
                }
            };
    
            greeting.sayHello(); // 调用接口方法
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    匿名内部类例子2(JavaAgent):
    常规写法是使用implements,但是使用匿名内部类更具有封装性和灵活性

    private static ClassFileTransformer createClassFileTransformer() {
            return new ClassFileTransformer() {
            @Override
            public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                                        ProtectionDomain protectionDomain, byte[] classfileBuffer) {...}
    }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    ddddocr基本使用和介绍
    谈谈Java/Kotlin中接口回调
    网络安全(黑客)自学
    工地反光衣识别检测系统
    速锐得解码TANK300烈马应用前大灯随动转向车灯照明系统DEMO
    安装SkyWalking 9.2.0
    C++信息学奥赛1181:整数奇偶排序
    相似图像的检测方法
    使用mysql语句操作数据表(table)
    高吞吐SFTP连接池设计方案
  • 原文地址:https://blog.csdn.net/weixin_45951067/article/details/128067785