Java

Java-反射

2020-09-01  本文已影响0人  Locker

1、动态语言和静态语言

2、反射

        Class<?> aClass = Class.forName("com.tools.server.Reflection.Test04_反射");
        Class<?> aClass1 = Class.forName("com.tools.server.Reflection.Test04_反射");
        Class<?> aClass2 = Class.forName("com.tools.server.Reflection.Test04_反射");
        System.out.println(aClass.hashCode());
        System.out.println(aClass1.hashCode());
        System.out.println(aClass2.hashCode());

打印:
471910020
471910020
471910020

3、Java反射机制提供的功能

4、Java反射优点和缺点

5、反射相关的主要API

6、Class类(678910做为class了解)

//Class类的创建方式
        //方式1、将类的路径作为参数,可能抛出ClassNotFoundException
        Class<?> aClass = Class.forName("com.tools.server.Reflection.User");

        //方式2、最安全可靠,性能高
        Class<User> aClass2 = User.class;

        //方式3、调用某个类的实例的getClass()方法获取
        User user = new User(1,20,"whl");
        Class<? extends User> aClass3 = user.getClass();

        System.out.println(aClass.hashCode());
        System.out.println(aClass2.hashCode());
        System.out.println(aClass3.hashCode());
        //打印结果:
        //          531885035
        //          531885035
        //          531885035
        Class c1 = Object.class;//类
        Class c2 = Comparable.class;//接口
        Class c3 = String[].class;//一维数组
        Class c4 = int[][].class;//二维数组
        Class c5 = void.class;//空类型
        Class c6 = Override.class;//注解
        Class c7 = ElementType.class;//枚举
        Class c8 = Integer.class;//基本数据类型

        System.out.println("c1:"+c1);    class java.lang.Object
        System.out.println("c2:"+c2);    interface java.lang.Comparable
        System.out.println("c3:"+c3);    class [Ljava.lang.String;
        System.out.println("c4:"+c4);    class [[I
        System.out.println("c5:"+c5);    void
        System.out.println("c6:"+c6);    interface java.lang.Override
        System.out.println("c7:"+c7);    class java.lang.annotation.ElementType
        System.out.println("c8:"+c8);    class java.lang.Integer

7、类加载内存分析




public class Test06 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.m);
        /*
        1.加载到内存,会产生一个类对应Class对象
        2.链接,链接结束后 m = 0
        3.初始化
            <clinit>(){
                System.out.println("静态代码块初始化");
                System.out.println("A方法无参构造初始化");
                m = 200;
                m = 100;
            }
         */
    }
}
class A{
    public A(){
        System.out.println("A方法无参构造初始化");
    }
    static{
        System.out.println("静态代码块初始化");
        m = 200;
    }
    static int m = 100;
}

1、方法区:先加载Test06类的信息
2、方法区:在加载A类的信息
3、堆:生成Test06和A类的class对象
4、栈:main方法初始化m=0,链接完毕,执行new A()
5、堆:new A():A类的对象可以代替(3、)去方法区找A类的信息
6、方法区:将类的初始值和静态代码块合并执行,返回到栈

8、什么时候会发生类初始化?

public class Test07_分析类的初始化 {
    
    static {
        System.out.println("main类被加载");
    }
    
    public static void main(String[] args) throws ClassNotFoundException {
        //主动引用
        //1、他会先加载父类,在加载子类
        Son son = new Son();
        //2、反射会引发主动引用:他使用java.lang.reflect包中的方法了
        Class.forName("com.tools.server.Reflection.Son");
        //3、调用类的静态方法
        Son.method_s();

        //被动引用
        //1、引用父类的静态变量或静态方法:不会导致子类初始化
        System.out.println(Son.b);
        Son.method_f();
        //2、数组定义类引用
        Son[] array = new Son[9];
        //3、引用常量
        System.out.println(Son.A);
    }
}
class Father{
    static int b = 2;
    static {
        System.out.println("父类被加载!");
    }
    public static void method_f(){
        System.out.println("method_f!");
    }
}
class Son extends Father{
    static int m = 100;
    static {
        System.out.println("子类被加载");
    }
    static final int A = 1;
    public static void method_s(){
        System.out.println("method_f!");
    }
}

9、类加载器

类加载器的作用.png
        //获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器-->扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类的父类加载器-->根加载器(c/c++)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);//引导类加载器是java核心类库,无法直接获取

        //测试当前类是哪个加载器加载的
        ClassLoader classLoader = Class.forName("com.tools.server.Reflection.Test08_类加载器").getClassLoader();
        System.out.println(classLoader);

        //测试JDK内置的类是哪个加载器加载的
        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader1);//引导类加载器是java核心类库,无法直接获取

        //如何获得系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));

10、获取类运行时结构

        Class aClass = Class.forName("com.tools.server.Reflection.User");
        //获取类名
        System.out.println(aClass.getSimpleName());//获取类名
        System.out.println(aClass.getName());//获取包名+类名
        /*打印:
            User
            com.tools.server.Reflection.User
         */

        //获取类的属性
        Field[] fields = aClass.getFields();//获取public属性
        Field[] fieldsall = aClass.getDeclaredFields();//获取全部的属性
        System.out.println("-----------------------------------------------------");
        for (int i = 0; i < fieldsall.length; i++) {
            System.out.println(fieldsall[i]);
        }
        /*打印:
            private int com.tools.server.Reflection.User.id
            private int com.tools.server.Reflection.User.age
            private java.lang.String com.tools.server.Reflection.User.name
         */

        //获取指定属性
        System.out.println("-----------------------------------------------------");
        System.out.println(aClass.getDeclaredField("name"));
        /*打印:
            private java.lang.String com.tools.server.Reflection.User.name
         */

        //获取类的方法
        System.out.println("-----------------------------------------------------");
        Method[] declaredMethodsall = aClass.getMethods();//获取本类和父类所有的public方法
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (int i = 0; i < declaredMethods.length; i++) {
            System.out.println(declaredMethods[i]);//获取本类的所有方法
        }
        /*打印:
            public java.lang.String com.tools.server.Reflection.User.toString()
            public java.lang.String com.tools.server.Reflection.User.getName()
            public void com.tools.server.Reflection.User.setName(java.lang.String)
            public int com.tools.server.Reflection.User.getId()
            public void com.tools.server.Reflection.User.setId(int)
            public int com.tools.server.Reflection.User.getAge()
            public void com.tools.server.Reflection.User.setAge(int)
            public void com.tools.server.Reflection.User.test()
         */

        //获取指定方法
        System.out.println("-----------------------------------------------------");
        System.out.println(aClass.getMethod("getAge", null));
        System.out.println(aClass.getMethod("setAge", int.class));
        /*打印:
            public int com.tools.server.Reflection.User.getAge()
            public void com.tools.server.Reflection.User.setAge(int)
         */

        //获取类全部的构造器
        System.out.println("-----------------------------------------------------");
        Constructor[] constructors = aClass.getConstructors();//获取本类构造器的public方法
        Constructor[] constructorsall = aClass.getDeclaredConstructors();//获取本类构造器的全部方法
        for (int i = 0; i < constructors.length; i++) {
            System.out.println(constructors[i]);
        }
        /*打印:
            public com.tools.server.Reflection.User(int,int,java.lang.String)
            public com.tools.server.Reflection.User()
         */

        //获取指定的构造器
        System.out.println("-----------------------------------------------------");
        Constructor declaredConstructor = aClass.getConstructor(int.class, int.class, String.class);
        System.out.println(declaredConstructor);
        /*打印:
            public com.tools.server.Reflection.User(int,int,java.lang.String)
         */

11、动态创建对象执行方法(通过反射创建对象)

        //获取class对象
        Class aClass = Class.forName("com.tools.server.Reflection.User");

        //构造一个对象
        User user = (User) aClass.newInstance();//本质是调用了无参构造器,如果类中没有无参构造器就会报错
        System.out.println(user);

        //通过构造器构造一个对象
        Constructor constructor = aClass.getDeclaredConstructor(int.class,int.class,String.class);//参数顺序不能变
        User user2 = (User) constructor.newInstance( 001, 18,"wyz");//参数顺序不能变,否则异常
        System.out.println(user2);

        //通过反射调用普通方法
        User user3 = (User) aClass.newInstance();
        System.out.println(user3.getName());
        //通过反射获取一个方法
        Method setName = aClass.getDeclaredMethod("setName", String.class);
        setName.invoke(user3,"whl");//invoke(激活)传递参数(对象,值)
        System.out.println(user3.getName());

        //通过反射操作属性
        User user4 = (User) aClass.newInstance();
        Field name = aClass.getDeclaredField("name");
        name.setAccessible(true);//取消安全检测,不加他访问不了private方法
        name.set(user4,"whl2");
        System.out.println(user4.getName());

12、性能对比

        User user = new User();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            user.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(endTime-startTime+" ms");//打印:4ms
        User user = new User();
        Class<?> aClass = Class.forName("com.tools.server.Reflection.User");//class获取对象
        Method getName = aClass.getDeclaredMethod("getName", null);//获取方法
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println(endTime-startTime+" ms");//打印:47ms
        User user = new User();
        Class<?> aClass = Class.forName("com.tools.server.Reflection.User");//class获取对象
        Method getName = aClass.getDeclaredMethod("getName", null);//获取方法
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            getName.invoke(user,null);
            getName.setAccessible(true);//关闭安全检测
        }
        long endTime = System.currentTimeMillis();
        System.out.println(endTime-startTime+" ms");//打印:17ms

通过反射还可以获取泛型、注解等,个人觉得没意义就不做展示了

上一篇 下一篇

猜你喜欢

热点阅读