反 射

1、什么是反射?

在java中,反射是指在运行时检查和操作类、接口、字段、方法等程序结构的能力。通过反射可以在运行时获取类的信息,创建类的实例,调用类的放方法,访问和修改类的字段等。

2、反射有什么作用?

主要用途: 反射最重要的用途就是开发各种通用框架。

反射也是框架技术的灵魂,而框架是他人写好并且包装起来的一套工具,把自己原先必须要写的,必须要做的一些复杂的东西都写好存放在那里,自己只需要调用他的方法即可。从而大大提高了开发效率。

3、如何获取反射?

获取Class类对象的方式有三种:

第一种: Class.forName("类路径")

第二种: 类名.class

第三中: 对象.getClass();

3.1 Class.ForName("类路径")

public class Text1 {

    public static void main(String[] args) throws ClassNotFoundException {
        //  通过Class.forName("类路径") 获取A的反射类对象
        Class<A> aClass = (Class<A>) Class.forName("com.dome.dome1.A");
        System.out.println("aClass:"+aClass);
    }

}
class A{
    private String a;
    private Integer b;

    @Override
    public String toString() {
        return "A{" +
                "a='" + a + '\'' +
                ", b=" + b +
                '}';
    }

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public Integer getB() {
        return b;
    }

    public void setB(Integer b) {
        this.b = b;
    }

    public A() {
    }

    public A(String a, Integer b) {
        this.a = a;
        this.b = b;
    }
}

运行结果:

3.2 类.class

public class Text1 {

    public static void main(String[] args) throws ClassNotFoundException {
        //  通过Class.forName("类路径") 获取A的反射类对象
//        Class<A> aClass = (Class<A>) 			    Class.forName("com.dome.dome1.A");
//        System.out.println("aClass:"+aClass);

        //  通过 类.class 获取A的反射类对象
        Class<A> aClass1 = A.class;
        System.out.println("aClass1:"+aClass1);
    }

}

运行结果:

3.3 对象.getClass();

public class Text1 {

    public static void main(String[] args) throws ClassNotFoundException {
        //  通过Class.forName("类路径") 获取A的反射类对象
//        Class<A> aClass = (Class<A>) Class.forName("com.dome.dome1.A");
//        System.out.println("aClass:"+aClass);

        //  通过 类.class 获取A的反射类对象
//        Class<A> aClass1 = A.class;
//        System.out.println("aClass1:"+aClass1);


       // 创建一个类
        A a = new A();
        // 通过 类.getClass(); 获取A的反射类对象
        Class<? extends A> aClass2 = a.getClass();
        System.out.println("aClass2:"+aClass2);


    }

}

运行结果:

4、通过反射类获取类对象

通过Class类对象,调用newInstance()(此方法在JDK9之后已过时)

public class Text2 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // 通过 Class.forName("类路径") 获取A的反射类对象
        Class<A> aClass = (Class<A>) Class.forName("com.dome.dome2.A");
        A a = aClass.newInstance();
        System.out.println("a"+a);

    }

}

运行结果:

总结:

​ 先通过Class.forName(“类路径”)——得到该类的反射类——并通过newInstance()创建类对象

5、获取反射类中的属性成员对象

由于字节码中的属性成员通过ClassLoader(类加载器)加载到内存中之后,会以Field(属性)类对象的形式存在。

首先说明一下getDeclaredFields()和getFields()这两个方法的区别:

getFields(): 获取某个类的所有的public字段,其中是包括父类的public字段的。

getDeclaredFields():获取某个类的自身的所有字段,不包括父类的字段。

5.1getFields()

public class Text3 {
    public static void main(String[] args) {
        //1、获取C类的反射类  类.class
        Class<C> cClass = C.class;
        // 2、获取反射类中的成员对象
//        // 获取本类中所有属性对象
//        Field[] declaredFields = cClass.getDeclaredFields();
//        for(Field field:declaredFields){
//            System.out.println("field:"+field);
//        }
        System.out.println("---------分割线-------------");
        // 获取本类及父类所有public字段
        Field[] fields = cClass.getFields();
        for (Field field1: fields){
            System.out.println("field1"+field1);
        }
    }
}

运行结果:
)

5.2 getDeclaredFields()

public class Text3 {
    public static void main(String[] args) {
        //1、获取C类的反射类  类.class
        Class<C> cClass = C.class;
        // 2、获取反射类中的成员对象
        // 获取本类中所有属性对象
        Field[] declaredFields = cClass.getDeclaredFields();
        for(Field field:declaredFields){
            System.out.println("field:"+field);
        }
    }
}
// 创建一个类
class B{
    public String b1;
    private Integer b2;
}
class C extends B{
    public Integer c1;
    private String c2;
    double c3;

    public void cc(){
        System.out.println("c1:"+c1+",c2:"+c2);
    }


    @Override
    public String toString() {
        return "C{" +
                "c1=" + c1 +
                ", c2='" + c2 + '\'' +
                ", c3=" + c3 +
                ", b1='" + b1 + '\'' +
                '}';
    }

    public Integer getC1() {
        return c1;
    }

    public void setC1(Integer c1) {
        this.c1 = c1;
    }

    public String getC2() {
        return c2;
    }

    public void setC2(String c2) {
        this.c2 = c2;
    }

    public double getC3() {
        return c3;
    }

    public void setC3(double c3) {
        this.c3 = c3;
    }

    public C() {
    }

    public C(Integer c1, String c2, double c3) {
        this.c1 = c1;
        this.c2 = c2;
        this.c3 = c3;
    }
}

运行结果:

)

6、Field类中具有的常用的方法

6.1 setAccessible(true)

setAccessible(true): 设置允许访问私有属性

public class Text5 {
    public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
        //  1、获取反射对象  类.getClass
        AA aa = new AA();
        Class<AA> aClass = (Class<AA>) aa.getClass();
        // 2、通过反射获取类对象
        AA aaa1 = aClass.newInstance();
        // 3、通过getDeclaredField()得到反射类中的aa1对象
        Field aa11 = aClass.getDeclaredField("aa1");
        aa11.setAccessible(true); // 允许访问私有属性
        //通过aa1属性对象为aaa1对象赋值
        aa11.set(aaa1,"欸嘿");
        System.out.println("aa11"+aa11);
    }

}
class AA{
    private String aa1;
    public Integer a1a;

    @Override
    public String toString() {
        return "AA{" +
                "aa1='" + aa1 + '\'' +
                ", a1a=" + a1a +
                '}';
    }
}

没有运行setAccessible(true)结果:(https://img2023.cnblogs.com/blog/3257079/202308/3257079-20230811105742840-955167904.png)
)

运行setAccessible(true)结果:

)

6.2 getAnnotation(注解.class)

public class Text5 {
    public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
        //  1、获取反射对象  类.getClass
        AA aa = new AA();
        Class<AA> aClass = (Class<AA>) aa.getClass();
        // 2、通过反射获取类对象
        AA aaa1 = aClass.newInstance();
        // 3、通过getDeclaredField()得到反射类中的aa1对象
        Field aa11 = aClass.getDeclaredField("aa1");
       aa11.setAccessible(true); // 允许访问私有属性
        //通过aa1属性对象为aaa1对象赋值
        aa11.set(aaa1,"欸嘿");
        System.out.println("aa11:"+aa11);

        System.out.println("-----------------分割线--------------");
        // 通过 反射类中aa11.getAnnotation(注解.class) 获取注解
        MyNote annotation = aa11.getAnnotation(MyNote.class);
        System.out.println("annotation"+annotation.value());

    }

}

运行结果:
)

7、获取方法类对象

7.1 getMethods()

getMethods(): 获得类的public类型的方法

public class Text6 {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        Class<E> eClass = E.class;
        E e = eClass.newInstance();
        // 获取本类及父类中所有的public修饰的Method方法对象
        Method[] methods = eClass.getMethods();
        for (Method method : methods) {
            System.out.println("method:"+method);
        }
    }

}
class E{
    public String fun01(){
        System.out.println("~~~~~~~~~~~~~~~~~01");
        return "hello01";
    }
    public String fun01(int age){
        System.out.println("~~~~~~~~~~~~~~~~~01");
        return "hello01";
    }
    public String fun02(int age){
        System.out.println("~~~~~~~~~~~~~~02");
        return "hello01"+age;
    }
    private void fun03(){
        System.out.println("~~~~~~~~~~~~~~~03");
    }

}

运行结果:
)

如果没有父类,会有默认的父类Object

7.2 getMethod(String name, Class[] params)

 getMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型(null和不写都调用无参的方法)

public class Text6 {
    public static void main(String[] args) throws Exception {
        Class<E> eClass = E.class;
        E e = eClass.newInstance();
        // 获取本类及父类中某一个的public修饰的Method方法对象
        Method methods = eClass.getMethod("fun01", int.class);
        System.out.println(methods);
    }

}

运行结果:

)

7.3 getDeclaredMethods()

getDeclaredMethods(): 获取本类中所有的方法(public、protected、default、private)

public class Text6 {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        Class<E> eClass = E.class;
        E e = eClass.newInstance();
        // 获取本类中所有的Method方法对象
        Method[] methods = eClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("method:"+method);
        }
    }

}

运行结果:

7.4 getDeclaredMethod(String name, Class[] params)

getDeclaredMethod(String name, Class[] params): 获得本类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型

public class Text6 {
    public static void main(String[] args) throws Exception {
        Class<E> eClass = E.class;
        E e = eClass.newInstance();
        // 获取本类中指定的public修饰的Method方法对象
        Method methods = eClass.getDeclaredMethod("fun02",new Class[]{int.class});
            System.out.println("method:"+methods);
    }
}

运行结果:

7.5 Method类中常用的方法

invoke(): 执行该方法体

public class Text6 {
    public static void main(String[] args) throws Exception {
        Class<E> eClass = E.class;
        E e = eClass.newInstance();
        // 获取本类中某一个的class对象的Method方法对象
        Method methods = eClass.getDeclaredMethod("fun02",new Class[]{int.class} );
        Object invoke = methods.invoke(e,15);
        System.out.println("invoke:"+invoke);
    }
}

运行结果:

)

8、获取构造方法对象

8.1 getConstructors()

getConstructors()获取Class对象所表示类的所有的公共构造方法

public class Text7 {
    public static void main(String[] args) {
        Class<Q> qClass = Q.class;
        // 只能得到本类中public的构造函数
        Constructor<Q>[] constructors = (Constructor<Q>[]) qClass.getConstructors();
        for (Constructor<Q> constructor : constructors) {
            System.out.println("constructor:"+constructor);
        }
    }
}
class R{
    public R(){
        System.out.println("父类的无参构造函数");
    }
    public R(String n){
        System.out.println("这是父类的有参构造函数:"+n);
    }
}
class Q extends R{
    public Q(){
        super();
        System.out.println("子类的无参");
    }
    public Q(String n){
        System.out.println("子类的有参:"+n);
    }
    private Q(Integer age){
        System.out.println("有参私有构造");
    }
}

运行结果:

)

8.2 getDeclaredConstructors()

getDeclaredConstructors()获取Class对象所表示的类声明的所有构造方法

public class Text7 {
    public static void main(String[] args) {
        Class<Q> qClass = Q.class;
         // 得到本类以及父类中public修饰的方法对象
        Constructor<Q>[] declaredConstructors = (Constructor<Q>[]) qClass.getDeclaredConstructors();
        for (Constructor<Q> declaredConstructor : declaredConstructors) {
            System.out.println("declaredConstructor:"+declaredConstructor);
        }
    }
}

运行结果:
)

8.3 getConstructor(Class<?>… parameterTypes)

getConstructor(Class<?>… parameterTypes)获取Class 对象所表示的类的指定公共构造方法

public class Text7 {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException {
        Class<Q> qClass = Q.class;
        Constructor<Q> Constructor = qClass.getConstructor(String.class);
        System.out.println("Constructor"+Constructor);
    }
}

运行结果:

8.4 getDeclaredConstructor(Class<?>… parameterTypes)

getDeclaredConstructor(Class<?>… parameterTypes)获取Class对象所表示的类声明的某个构造方法

public class Text7 {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException {
        Class<Q> qClass = Q.class;

        Constructor<Q> declaredConstructor = qClass.getDeclaredConstructor(String.class);
        System.out.println("declaredConstructor"+declaredConstructor);
    }
}

运行结果:
)

8.5 Constructor类中常用的方法

public class Text7 {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<Q> qClass = Q.class;
        Constructor<Q> constructor = qClass.getConstructor(String.class);
        constructor.newInstance("欸嘿  欸嘿");
    }
}

运行结果:

posted @ 2023-08-11 11:03  蝶凌天  阅读(4)  评论(0编辑  收藏  举报