反射

…衆ロ難τιáo~ 提交于 2020-01-24 01:24:02

反射

1.获得反射对象的几种方式

//测试Class类的创建方式有哪些
public class test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是" + person.name);

        //方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());

        //方式二:forname获得
        Class c2 = Class.forName("com.kk.reflection.Student");
        System.out.println(c2.hashCode());

        //方式三:通过类名.class
        Class<Student> c3 = Student.class;
        System.out.println(c3.hashCode());

        //方式四:基本内置类型的包装类都有一个TYPE属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);

        //获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);


    }
}

class Person {
    String name;

    public Person() {

    }

    public Person(String name) {
        this.name = name;
    }
}


class Student extends Person {
    public Student() {
        this.name = "学生";
    }
}


class Teacher extends Person {
    public Teacher() {
        this.name = "教师";
    }
}

2.所有类型的Class对象

public class test03 {
    public static void main(String[] args) {
        Class c1 = Object.class;//类
        Class c2 = Comparable.class;//接口
        Class c3 = String[].class;//一维数组
        Class c4 = int[][].class;//二维数组
        Class c5 = Override.class;//注解
        Class c6 = ElementType.class;//枚举
        Class c7 = Integer.class;//基本数据类型
        Class c8 = void.class;//void
        Class c9 = Class.class;//Class


        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

        int[] a = new int[10];
        int[] b = new int[20];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());

    }
}

3.类加载内存分析

 

  • //加载:首先,类会编译成class文件加载到内存中的 方法区,(test04类和A类)包含静态变量、静态方法、常量池、代码等,加载完成后会立即在 堆 中产生对应的两个java.lang.Class对象,这个对象代表了该类的结构,
  • //链接:执行栈中的main方法,在 堆 中new一个A类对象a,a对象会去找自己的Class类,拿到该类的结构和数据
  • //初始化:自动执行构造器<clinit>(),由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句进行合并
     
public class test04 {
    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("A类的静态代码块");
                    m = 300;
                    m = 100;
                }
               所以m=100
        */
    }
}

class A{
    static {
        System.out.println("A类的静态代码块");
        m = 300;
    }

    static int m = 100;

    public A(){
        System.out.println("A类的无参构造初始化");
    }
}


//加载:首先,类会编译成class文件加载到内存中的 方法区,(test04类和A类)包含静态变量、静态方法、常量池、代码等,加载完成后会立即在 堆 中产生对应的两个java.lang.Class对象,这个对象代表了该类的结构,
//链接:执行栈中的main方法,在 堆 中new一个A类对象a,a对象会去找自己的Class类,拿到该类的结构和数据
//初始化:自动执行构造器<clinit>(),由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句进行合并

4.类初始化

//测试类什么时候会初始化
//总结:只有类的主动引用,或通过反射去调用的时候才会发生类的初始化
public class test05 {
    static {
        System.out.println("Main类被加载");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //1.主动引用
//        Son son = new Son();

        //反射也会产生主动引用
//        Class.forName("com.kk.reflection.Son");


        //不会产生类的引用的情况
        //1.子类调用父类的静态成员[不会加载子类]
//        System.out.println(Son.b);

        //2.数组
//        Son[] sons = new Son[3];

        //3.调用子类常量池中的成员
        System.out.println(Son.M);

//因为常量和类的静态成员,在链接阶段就存入调用类的常量池中了

    }
}

class Father{

    static int b = 2;

    static{
        System.out.println("父类被加载");
    }
}
class Son extends Father{
    static {
        System.out.println("子类被加载");
        m = 300;
    }
    static int m = 100;
    //常量
    static final int M = 1;
}

详解

(加载器)

public class test06 {
    public static void main(String[] args) throws ClassNotFoundException {

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

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

        //获取扩展类加载器的父类加载器-->根加载器(C/C++)
        //java平台核心库,该加载类无法直接获取,返回null
        ClassLoader parent1 = parent.getParent();
        System.out.println("引导类加载器"+parent1);

        System.out.println("--------------------------------------------------");

        //测试当前类是哪个加载器加载的
        ClassLoader classLoader0 = Class.forName("com.kk.reflection.test06").getClassLoader();
        System.out.println(classLoader0);

        //测试JDK内置的类是谁加载的
        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader1);

        System.out.println("--------------------------------------------------");

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

    }
}
//系统类加载器可以加载的路径
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar;
// C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar;
// F:\IDEA_Project_Location\狂神\注解和反射\out\production\注解和反射;
// F:\IDEA\IntelliJ IDEA 2018.2.4\lib\idea_rt.jar

(创建运行时类的对象,获取类运行时的完整结构)

public class test07 {
    public static void main(String[] args) throws Exception {

        Class c1 = Class.forName("com.kk.reflection.User");

        //获得类的名字
        System.out.println(c1.getName());//获取报名+类名
        System.out.println(c1.getSimpleName());//获取类名

        //获取类的属性
        System.out.println();
        System.out.println("***************************************");
        System.out.println();

        //只能找到public属性
        Field[] fields = c1.getFields();

        //找到全部属性
        fields = c1.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        //获得指定属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);



        //获取类的方法
        System.out.println();
        System.out.println("========================================");
        System.out.println();

        //1.获得本类的及其父类的全部public方法
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println("正常的:"+method);
        }
        System.out.println("--------------------------------------------");
        //2.获得本类的所有方法
        methods = c1.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        System.out.println("--------------------------------------------");
        //3.获得指定方法
        Method getId = c1.getMethod("getId", null);
        Method setId = c1.getMethod("setId", int.class);
        System.out.println(getId);
        System.out.println(setId);


        //获取类的构造器
        System.out.println();
        System.out.println("========================================");
        System.out.println();

        //1.获得本类的public全部的构造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        //2.获得本类全部的构造方法
        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("#"+constructor);
        }

        //3.获得指定的构造器
        Constructor constructor = c1.getConstructor(String.class, int.class, int.class);
        System.out.println("指定"+constructor);

    }
}

(通过反射动态创建对象,调用方法,操作属性)

//通过反射动态创建对象,调用方法,操作属性
public class test08 {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得Class对象
        Class c1 = Class.forName("com.kk.reflection.User");

//创建对象
        //1.newInstance创建对象
        User user = (User)c1.newInstance();//本质上是调用了类的无参构造器
        System.out.println(user);

        //2.通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        Object user2 = constructor.newInstance("kzj", 001, 22);
        System.out.println(user2);

        System.out.println("------------------------------------------------------");


//通过反射调用普通方法
        User user3 = (User)c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //invoke激活,传入要使用该方法的对象,和该方法需要参数
        setName.invoke(user3, "康梓健");
        System.out.println(user3.getName());

        System.out.println("------------------------------------------------------");


//通过反射操作属性
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");

        //关掉权限检测
        name.setAccessible(true);//设置为true,就是关掉

        //本来User类中的属性都是private的,不能操作,但是可以关掉权限检测
        name.set(user4, "彭于晏");
        System.out.println(user4.getName());
    }

}

(获取注解信息)

import java.lang.annotation.*;
import java.lang.reflect.Field;

//练习反射操作注解
public class test09 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {

        Class c1 = Class.forName("com.kk.reflection.Student2");

        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        //获得Tablekk注解的value的值
        Tablekk tablekk = (Tablekk)c1.getAnnotation(Tablekk.class);
        String value = tablekk.value();
        System.out.println(value);


        //获得指定字段的注解中的属性
        Field f = c1.getDeclaredField("name");
        Fieldkk annotation = f.getAnnotation(Fieldkk.class);
        System.out.println(annotation.columName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());


    }

}
@Tablekk("db_student")
class Student2{
    @Fieldkk(columName = "db_id",type = "int",length = 10)
    private int id;
    @Fieldkk(columName = "db_age",type = "int",length = 10)
    private int age;
    @Fieldkk(columName = "db_name",type = "String",length = 3)
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Student2(){

    }

    public Student2(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tablekk{
    String value();
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldkk{
    String columName();
    String type();
    int length();
}

 

哔哩哔哩:https://www.bilibili.com/video/av55440782?p=5

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!