栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

03Java反射学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

03Java反射学习笔记

              Java反射学习笔记

文章目录
  • 1 反射简介
    • 1.1 什么是反射
    • 1.2 反射的好处
    • 1.3 Java代码在计算机中经历的三个阶段
    • 1.4 获取Class对象的方式
  • 2 class对象功能
    • 2.1 获取成员变量
    • 2.2 获取构造方法
    • 2.3 获取成员方法
    • 2.4 获取类名
  • 3 成员变量Field功能
    • 3.1 获取值
    • 3.2 设置值
    • 3.3 暴力反射
  • 4 构造方法功能
    • 4.1 创建对象
    • 4.2 暴力反射
  • 5 成员方法功能
    • 5.1 执行方法
    • 5.2 获取方法名
    • 5.3 暴力反射
  • 6 写一个框架
    • 6.1 需求
    • 6.2 步骤
    • 6.3 代码

1 反射简介 1.1 什么是反射

​ 反射:框架设计的灵魂

​ 将类的各个组成部分封装为其他对象,这就是反射。

1.2 反射的好处

​ 1.可以在程序运行过程中,操作这些对象

​ 2.可以解耦,提高程序的可扩展性

1.3 Java代码在计算机中经历的三个阶段

1.4 获取Class对象的方式

​ 1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象 ----多用于配置文件,读取文件,加载类 如struts2配置文件

​ 2.类名.Class : 通过类名的属性class获取 ----多用于参数的传递

​ 3.对象.Class : getClass()方法在Object类中定义着。 --多用于对象的获取字节码

结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

2 class对象功能

Person.java

package com.tangguanlin.reflect;

public class Person {

    private  String name;
    private int age;

    public String a;
    protected String b;
    String c;
    private  String d;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", a='" + a + ''' +
                ", b='" + b + ''' +
                ", c='" + c + ''' +
                ", d='" + d + ''' +
                '}';
    }
}
2.1 获取成员变量
   	Field[] getFields() :           获取所有public修饰的成员变量
   	Field   getField(String name) : 获取指定名称的public修饰的成员变量
   	
   	Field[] getDeclaredFields() :   获取所有的成员变量(不考虑修饰符)
   	Field   getDeclaredField(String name):  获取指定名称的成员变量(不考虑修饰符)

代码:

ReflectTest2.java

package com.tangguanlin.reflect;
import java.lang.reflect.Field;

public class ReflectTest2 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //0.获取Person的Class对象
        Class personClass = Person.class;

        //1 获取成员变量
        Field[] fields = personClass.getFields();
        for(Field field:fields){
            System.out.println(field);
        }

        Field[] declaredFields = personClass.getDeclaredFields();
        for(Field field:declaredFields){
            System.out.println("getDeclaredFields:"+field);
        }

        Field a = personClass.getField("a");
        //获取成员变量a的值
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);
        //设置成员变量a的值
        a.set(p,"张三");
        System.out.println(p);

        Field nameField = personClass.getDeclaredField("name");
        System.out.println("getDeclaredField:"+nameField);
        //忽略访问权限修饰符的安全检查
        nameField.setAccessible(true);  //暴力反射
        nameField.get(p);
        nameField.set(p,"lisi");
        System.out.println(p);
    }
}

运行结果:

public java.lang.String com.tangguanlin.reflect.Person.a
getDeclaredFields:private java.lang.String com.tangguanlin.reflect.Person.name
getDeclaredFields:private int com.tangguanlin.reflect.Person.age
getDeclaredFields:public java.lang.String com.tangguanlin.reflect.Person.a
getDeclaredFields:protected java.lang.String com.tangguanlin.reflect.Person.b
getDeclaredFields:java.lang.String com.tangguanlin.reflect.Person.c
getDeclaredFields:private java.lang.String com.tangguanlin.reflect.Person.d
null
Person{name='null', age=0, a='张三', b='null', c='null', d='null'}
getDeclaredField:private java.lang.String com.tangguanlin.reflect.Person.name
Person{name='lisi', age=0, a='张三', b='null', c='null', d='null'}
2.2 获取构造方法
Constructor[]    getConstructors() :                      获取所有public修饰的构造方法
Constructor      getConstructor(String.class, int.class);  获取指定参数类型的public修饰的构造方法

Constructor[]    getDeclaredConstructors():               获取所有的构造方法(不考虑修饰符)
Constructor      getDeclaredConstructor(String.class, int.class) 获取指定参数类型的构造方法(不考虑修饰符)

代码:

ReflectTest3.java

package com.tangguanlin.reflect;
import org.apache.poi.util.SystemOutLogger;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class ReflectTest3 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        //0.获取Person的Class对象
        Class personClass = Person.class;

        //1.获取构造方法
        Constructor[] constructors = personClass.getConstructors();
        for(Constructor constructor:constructors){
            System.out.println("--getConstructors()--"+constructor);
        }

        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);


        Constructor[] declaredConstructors = personClass.getDeclaredConstructors();
        for(Constructor declaredConstructor:constructors){
            System.out.println("--getDeclaredConstructors()--"+declaredConstructor);
        }

        Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class, int.class);
        System.out.println("--getDeclaredConstructor()--"+declaredConstructor);

        //用构造方法创建对象
        Object p5 = constructor.newInstance("wangwu", 23);
        System.out.println(p5);

        Constructor constructor1 = personClass.getDeclaredConstructor();
        Object p6 = constructor1.newInstance();
        System.out.println(p6);

        //等价于
        Object p7 = personClass.newInstance();
        System.out.println(p7);

        //暴力反射
        constructor1.setAccessible(true);
    }
}

运行结果:

--getConstructors()--public com.tangguanlin.reflect.Person(java.lang.String,int)
--getConstructors()--public com.tangguanlin.reflect.Person()
public com.tangguanlin.reflect.Person(java.lang.String,int)
--getDeclaredConstructors()--public com.tangguanlin.reflect.Person(java.lang.String,int)
--getDeclaredConstructors()--public com.tangguanlin.reflect.Person()
--getDeclaredConstructor()--public com.tangguanlin.reflect.Person(java.lang.String,int)
Person{name='wangwu', age=23, a='null', b='null', c='null', d='null'}
Person{name='null', age=0, a='null', b='null', c='null', d='null'}
Person{name='null', age=0, a='null', b='null', c='null', d='null'}
2.3 获取成员方法
Method[] getMethods()   :				 	 获取所有public修饰的成员方法
Method   getMethod(方法名称, int.class):       获取指定方法名称的public修饰的成员方法
 
Method[] getDeclaredMethods() :                  获取所有的成员方法(不考虑修饰符)
Method   getDeclaredMethods(方法名称, int.class):  获取指定方法名的成员方法(不考虑修饰符)

代码:

​ ReflectTest4.java

package com.tangguanlin.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectTest4 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //0.获取Person的Class对象
        Class personClass = Person.class;

        //1.获取所有public成员方法
        Method[] methods = personClass.getMethods();
        for(Method method:methods){
            System.out.println("--getMethods()--"+method);
        }
		//获取指定名称的成员方法
        Method eatMethod = personClass.getMethod("eat", int.class);
        Person p = new Person();

        //执行成员方法
        eatMethod.invoke(p, 5);

        //获取所有的成员方法(不考虑修饰符)
        Method[] declaredMethods = personClass.getDeclaredMethods();
        for(Method declaredMethod:declaredMethods){
            System.out.println("--getDeclaredMethods()--"+declaredMethod);
        }
    }
}

运行结果:

--getMethods()--public java.lang.String com.tangguanlin.reflect.Person.toString()
--getMethods()--public java.lang.String com.tangguanlin.reflect.Person.getName()
--getMethods()--public void com.tangguanlin.reflect.Person.setName(java.lang.String)
--getMethods()--public void com.tangguanlin.reflect.Person.eat(int)
--getMethods()--public int com.tangguanlin.reflect.Person.getAge()
--getMethods()--public void com.tangguanlin.reflect.Person.setAge(int)
--getMethods()--public final void java.lang.Object.wait() throws java.lang.InterruptedException
--getMethods()--public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
--getMethods()--public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
--getMethods()--public boolean java.lang.Object.equals(java.lang.Object)
--getMethods()--public native int java.lang.Object.hashCode()
--getMethods()--public final native java.lang.Class java.lang.Object.getClass()
--getMethods()--public final native void java.lang.Object.notify()
--getMethods()--public final native void java.lang.Object.notifyAll()
eat0...
eat1...
eat2...
eat3...
eat4...
--getDeclaredMethods()--public java.lang.String com.tangguanlin.reflect.Person.toString()
--getDeclaredMethods()--public java.lang.String com.tangguanlin.reflect.Person.getName()
--getDeclaredMethods()--public void com.tangguanlin.reflect.Person.setName(java.lang.String)
--getDeclaredMethods()--public void com.tangguanlin.reflect.Person.eat(int)
--getDeclaredMethods()--public int com.tangguanlin.reflect.Person.getAge()
--getDeclaredMethods()--public void com.tangguanlin.reflect.Person.setAge(int)
--getDeclaredMethods()--private void com.tangguanlin.reflect.Person.sing()
2.4 获取类名

语法:personClass.getName()

//获取类名
String className = personClass.getName();
System.out.println("获取类名:"+className);

运行结果:

获取类名:com.tangguanlin.reflect.Person
3 成员变量Field功能 3.1 获取值
  String value = a.get(p);

3.2 设置值
a.set(p,"张三");
3.3 暴力反射

​ 忽略访问权限修饰符的安全检查

#忽略访问权限修饰符的安全检查
nameField.setAccessible(true); 
4 构造方法功能 4.1 创建对象

​ 构造方法Constructor功能:创建对象

Object p5 = constructor.newInstance("wangwu", 23);


Constructor constructor = personClass.getDeclaredConstructor(); //空参构造函数
Object p6 = constructor.newInstance();
//等价于
Object p7 = personClass.newInstance();  //一般使用这种方式
4.2 暴力反射

​ 构造方法 也有暴力反射

Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class, int.class);
//暴力反射
declaredConstructor.setAccessible(true);
5 成员方法功能 5.1 执行方法

语法:eatMethod.invoke(对象, 方法参数列表);

//获取指定名称的成员方法
Method eatMethod = personClass.getMethod("eat", int.class);
Person p = new Person();

//执行成员方法
eatMethod.invoke(p, 5); 
5.2 获取方法名
//获取指定名称的成员方法
Method eatMethod = personClass.getMethod("eat", int.class);

//获取成员方法名称
System.out.println("eat方法名"+eatMethod.getName());

运行结果:

eat方法名eat
5.3 暴力反射
//获取指定名称的成员方法
Method eatMethod = personClass.getMethod("eat", int.class);

//成员方法暴力反射
eatMethod.setAccessible(true);
6 写一个框架

案例:体现反射的魅力所在

6.1 需求

​ 需求:写一个“框架”,不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法

​ 实现:

​ 1.配置文件

​ 2.反射

6.2 步骤

步骤

​ 1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中

​ 2.在程序中加载读取配置文件

​ 3.使用反射技术来加载类文件进内存

​ 4.创建对象

​ 5.执行方法

6.3 代码

Person.java

package com.tangguanlin.reflect;

public class Person {

    public void sing(){
        System.out.println("sing...");
    }
}

Student.java

package com.tangguanlin.reflect;

public class Student {

    public void sleep(){
        System.out.println("sleep...");
    }
}

pro.properties配置文件

className=com.tangguanlin.reflect.Person
methodName=sing

ReflectTest5.java

package com.tangguanlin.reflect;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectTest5 {
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //可以执行创建任意类的对象,可以执行任意方法

        //1.加载配置文件
        //1.1创建Properties对象
        Properties pro =  new Properties();  //专门读取properties文件的工具
        //1.2加载配置文件,转换为一个集合
        //1.2.1 获取class目录下的配置文件
          //获取类加载器
        ClassLoader classLoader = ReflectTest5.class.getClassLoader();
           //用类加载器加载配置文件
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        //FileInputStream fis = new FileInputStream("pro.properties");  //等价

        pro.load(is);

        //2.获取配置文件中定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //3.加载该类进内存
        Class c1= Class.forName(className);
        //4.创建对象
        Object object  = c1.newInstance();
        // 5.获取方法对象
        Method method = c1.getMethod(methodName);
        //6.执行方法
        method.invoke(object);
    }
}

运行结果:

sing...

修改配置文件pro.properties

className=com.tangguanlin.reflect.Student
methodName=sleep

运行结果:

sleep...
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/691861.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号