2021-11-09  2021-11-09    2813 字   6 分钟

反射

概念

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。

这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制

Class

Class 类的实例表示正在运行的 Java 应用程序中的类和接口

package com.demo;
/**
 1.获取Class类的对象
 ① forName(String className)
    注意: 参数必须是类的完全限定名。
 ② .class
 ③  getClass()
 */
public class 反射概述 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person p = new Person();
//        p.show();
        Class clazz = p.getClass();
        System.out.println(clazz);
        Class clazz1 = Person.class;
        System.out.println(clazz1);
        //Person 简名
        Class clazz2 = Class.forName("com.demo.Person");
        System.out.println(clazz2);
    }
}
class Person{
    String name;
    int age;
    public void show(){}
}

Class类对象的获取

① forName(String className)

② .class

③ getClass()

类的加载

1.类加载过程:按需加载,并且只加载一次。

如果需要用到该类,在方法区中查找是否有该类存在,如果存在,直接使用,如果不存在,将硬盘

上.class通过类加载器加载进内存。 将.class文件转换成Class类的对象。该对象只有一个,该对象

代表的是类。

准备: 静态成员开辟空间。

类的连接 : 验证 准备 解析

2.类加载机制: 双亲委派机制 父类加载

加载到方法区中的类需要保证唯一性,采用双亲委派,父类加载的机制。 1.启动/引导类加载器 2.扩展类加载器 3.应用程序/系统程序类加载器

反射创建对象

概述

1.Jvm中通过Class对象来创建该对象代表的类的对象

2.常用方法:

① newInstance() 调用空参的构造方法创建对象 

② getConstructors() 获取所有的构造方法 

③ getConstructor(Class<?>... parameterTypes) 

3.Constructor:表示构造方法类

① newInstance(Object... initargs) 创建对象 

代码

package com.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
  1.Jvm中通过Class对象来创建该对象代表的类的对象
  2.常用方法:
     ① newInstance() 调用空参的构造方法创建对象
     ② getConstructors()  获取所有的构造方法
     ③ getConstructor(Class<?>... parameterTypes)
  3.Constructor:表示构造方法类
    ① newInstance(Object... initargs) 创建对象

 */
public class Class类对象的常用方法 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//         A a = new A();
       /* Class clazz = Class.forName("com.demo.A");
        A a = (A) clazz.newInstance();
        a.show();
        Class clazz1 = B.class;
        B b = (B) clazz1.newInstance();
        System.out.println(b);*/

//        ② getConstructors()  获取所有的构造方法
        Class clazz2 = A.class;
       /* Constructor[] cs = clazz2.getConstructors();
        for (Constructor c : cs) {
            System.out.println(c);
        }*/
        Constructor cn = clazz2.getConstructor(String.class, int.class);
//        A  a1 = new A("张三",19);
        A o = (A) cn.newInstance("张三", 19);
//        System.out.println(cn);
        o.show();
    }
}
class A{
    String name;
    int age;
    public void show(){
        System.out.println(name +":"+age);
    }

    public A() {
    }

    public A(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
class B {}
package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
  1.getConstructors()细节问题:
   注意:凡是只有getXXX的形式,都只能获取public修饰的。如果需要获取
 其它的权限的时候,使用getDeclaredXXX()
 2.关于private访问权限的取消:
 setAccessible(boolean flag) 如果参数为true 表示取消java的语法访问检测,称为打开权限。
 */
public class Class类创建对象 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Person.class;
        /*Constructor[] cs = clazz.getDeclaredConstructors();
        for (Constructor c : cs) {
            System.out.println(c);
        }*/
        Constructor c = clazz.getDeclaredConstructor(String.class, int.class);
        //打开权限
        c.setAccessible(true);
        Person p = (Person) c.newInstance("张三", 19);
        p.show();
    }
}
class Person{
    String name;
    int age;
    public void show(){
        System.out.println(name +":"+ age);
    }

    public Person() {
    }

   private  Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

反射构造方法的细节问题

概述

1.getConstructors()细节问题:

注意:凡是只有getXXX的形式,都只能获取public修饰的。如果需要获取

其它的权限的时候,使用getDeclaredXXX(),该形式只能用于本类声明,但是getXXX的形式,如果

父类是public也可以获取。

2.关于private访问权限的取消:

setAccessible(boolean flag) 如果参数为true 表示取消java的语法访问检测,称为打开权限。

代码

package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
  1.getConstructors()细节问题:
   注意:凡是只有getXXX的形式,都只能获取public修饰的。如果需要获取
 其它的权限的时候,使用getDeclaredXXX()
 2.关于private访问权限的取消:
 setAccessible(boolean flag) 如果参数为true 表示取消java的语法访问检测,称为打开权限。
 */
public class Class类创建对象 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Person.class;
        /*Constructor[] cs = clazz.getDeclaredConstructors();
        for (Constructor c : cs) {
            System.out.println(c);
        }*/
        Constructor c = clazz.getDeclaredConstructor(String.class, int.class);
        //打开权限
        c.setAccessible(true);
        Person p = (Person) c.newInstance("张三", 19);
        p.show();
    }
}
class Person{
    String name;
    int age;
    public void show(){
        System.out.println(name +":"+ age);
    }

    public Person() {
    }

   private  Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

反射获取属性(字段field)

概述

1.获取字段:

① getField(String name) 指定的修饰符为public字段 

② getFields() 修饰符为public所有字段 

③ getDeclaredField(String name) 指定的声明的字段 

④ getDeclaredFields() 指定的声明所有的字段 

2.设置/获取字段值 setter getter

① set(Object obj, Object value) /get(Object obj)

代码

package com.demo;

import java.lang.reflect.Field;

/**
   1.获取字段:
    ① getField(String name) 指定的修饰符为public字段
    ② getFields() 修饰符为public所有字段
    ③ getDeclaredField(String name) 指定的声明的字段
    ④ getDeclaredFields() 指定的声明所有的字段
   2.设置/获取字段值  setter getter
    ① set(Object obj, Object value) /get(Object obj)
 */
public class 字段 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class clazz = Student.class;
        Field age = clazz.getField("age");
        /*System.out.println(age);
        Class clazz1 = MiddleStudent.class;
        Field age1 = clazz1.getField("age");
        System.out.println(age1);*/
        Student st = (Student) clazz.newInstance();
        /*age.set(st, 20);
        System.out.println(age.get(st));*/
        Field name = clazz.getDeclaredField("name");
        //打开权限
        name.setAccessible(true);
        name.set(st, "张三");
        st.show();
    }
}
class Student{
   private String name;
   public  int age;
    public void show(){
        System.out.println(name +":"+ age);
    }

    public Student() {
    }

    private  Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
class  MiddleStudent extends  Student{}

反射之方法

概念

1.获取方法:

① getMethod(String name, Class<?>... parameterTypes) 

② getMethods() 

③ getDeclaredMethod(String name, Class<?>... parameterTypes) 

④ getDeclaredMethods() 

2.调用方法:

invoke(Object obj, Object... args) 

① 第一个参数表示对象,如果是静态方法可以置为null 

② 第二个参数表示方法的实参,如果没有参数也可以置为null或不写。 

③ 该方法的返回值为方法调用的返回值。 

            void 返回值为null

代码

package com.demo;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
  1.获取方法:
    ① getMethod(String name, Class<?>... parameterTypes)
    ② getMethods()
    ③ getDeclaredMethod(String name, Class<?>... parameterTypes)
    ④ getDeclaredMethods()
  2.调用方法:
    invoke(Object obj, Object... args)
     ① 第一个参数表示对象,如果是静态方法可以置为null
     ② 第二个参数表示方法的实参,如果没有参数也可以置为null或不写。
     ③ 该方法的返回值为方法调用的返回值。
          void 返回值为null
 */
public class 方法 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //先找到Class
        Class clazz = Worker.class;
        //创建Worker类的对象
        Worker wr = (Worker) clazz.newInstance();
        //获取show方法 由于该方法没有参数,可以使用null或直接省略不写。
        /*Method show = clazz.getMethod("show");
        Object value = show.invoke(wr);
        System.out.println(value);*/

        /*Method working = clazz.getMethod("working", String.class);
        Object value1 = working.invoke(wr, "建筑");
        System.out.println(value1);*/

        Method add = clazz.getMethod("add", int.class, int.class);
        int value2 = (int) add.invoke(wr, 15, 23);
        System.out.println(value2);

        Method fun = clazz.getMethod("fun" );
        Object value3 = fun.invoke(null);

    }
}
class  Worker{
    String name;
    int age;
    public void show(){
        System.out.println(name +":"+ age);
    }
    public void working(String action){
        System.out.println("工人从事"+action+"行业");
    }
    public int add(int a,int b){
        return a+b;
    }
    public static void fun(){
        System.out.println("aaaaa");
    }
}

反射总结

概述

概念 Class 获取方式三种 字段 set/get 构造方法 newInstance 方法 invoke

反射的其它方法

package com.demo;
/**
  1.getInterfaces() 获取父接口
  2.getName() 返回类/接口的完全限定名。
  3.getSuperclass()获取父类
  4.getClassLoader() 获取类加载器

 */
public class 反射的其它方法 {
    public static void main(String[] args) {
        Class  clazz = ZiA.class;
        /*Class[] in = clazz.getInterfaces();
        for (Class aClass : in) {
            System.out.println(aClass.getName());
        }*/
        /*Class sc = clazz.getSuperclass();
        System.out.println(sc);*/
        ClassLoader cl = clazz.getClassLoader();
        System.out.println(cl.getParent().getParent());
    }

}
class A {

}
interface T{}
class ZiA extends A implements  T{}

暴力反射

package com.exec;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class 暴力反射 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        Class clazz = list.getClass();
        Method add = clazz.getMethod("add", Object.class);
        add.invoke(list, "abc");
        System.out.println(list);
    }
}

来电显示

package com.exec;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
/**
  1.手机的来电显示:
  2.配置文件。xml
 */
public class 来电显示 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        Properties prp = new Properties();
        prp.load(new FileReader(new File("day27b\\p.properties")));
        Class clazz = Class.forName(prp.getProperty("className"));
        PhoneI  pi = (PhoneI) clazz.newInstance();
        pi.display();
    }
}
class PhoneI{
    public void display(){
        System.out.println("显示号码");
    }
}
class PhoneII extends PhoneI{
    @Override
    public void display() {
        super.display();
        System.out.println("大头贴");
    }
}
class PhoneIII extends  PhoneII{
    @Override
    public void display() {
        super.display();
        System.out.println("归属地。。。");
    }
}
class PhoneIIII extends  PhoneIII{}

avatar
青山
悟已往之不谏 知来者之可追
一言
今日诗词
站点信息
本站访客数 :
本站总访问量 :