Java反射机制知识总结

概念:反射就是把java类中的各个组成部分映射成相应的Java类。

  • 一个类的组成部分包括:属性、方法、构造方法、包等。这些组成部分都会反射成相应的类。

  • Class类定义了一系列方法来获取Java类的属性、方法、构造方法、包等信息,这些信息都有相应的类来表示,分别是Field、Method、Constructor、Pacage等。

  • 表示java类组成部分的各种类位于java.lang.reflect包中。

Class对象基本概念

Java当中的类用来表示具有相同属性和方法的对象的结合,是抽象的概念。对象是类创建的,同一个类的不同对象具有不同的属性值。

Java当中定义的所有类都属于同一类事物,可以用Class来表示。

Class类的对象就是不同类对应的字节码。

获取Class的三种方法:

(1)对象名.getClass()

 Person p1 = new Person();  

 p1.getClass();

(2)类名.class

 Data.class

(3)Class.forName()方法

 Class.forName("java.lang.String");

Java中的基本数据类型也有各自的Class对象

例如:int.class

void 也有自己对应的Class对象 void.class

基本数据类型对应的封装类有属性TYPE,这个属性代表了封装类所封装的基本数据类型的Class对象。

System.out.println(int.class==Integer.TYPE);

System.out.println(boolean.class==Boolean.TYPE);

System.out.println(int.class.getName());

运行结果:

true

true

int

 Class类常用的方法:

类型

访问方法

返回值类型

说明

包路径

getPackage()

Package 对象

获取该类的存放路径

类名称

getName()

String 对象

获取该类的名称

继承类

getSuperclass()

Class 对象

获取该类继承的类

实现接口

getlnterfaces()

Class 型数组

获取该类实现的所有接口

构造方法

getConstructors()

Constructor 型数组

获取所有权限为 public 的构造方法

getDeclaredContruectors()

Constructor 对象

获取当前对象的所有构造方法

方法

getMethods()

Methods 型数组

获取所有权限为 public 的方法

getDeclaredMethods()

Methods 对象

获取当前对象的所有方法

成员变量

getFields()

Field 型数组

获取所有权限为 public 的成员变量

getDeclareFileds()

Field 对象

获取当前对象的所有成员变量

 Class对象的基本使用:

要进行反射操作必需要拿到这个类对应的Class对象:

Class class2 = Class.forName("com.zjb.ssm.reflect.Person");
Package pac = class2.getPackage(); //通过Class对象的getPackage()方法可以获取到package;
System.out.println(pac.getName());
Constructor con = class2.getConstructor();//通过Class对象的getConstructor()方法可以获取到Constructor;
System.out.println(con.getName());
Person person1 = (Person) con.newInstance();//通过反射的方式创建对象;
Person person2 = (Person) con.newInstance();
System.out.println(person1);
System.out.println(person2);
Constructor con2 = class2.getConstructor(Integer.class,String.class,String.class,Integer.class,String.class);
//getConstructor()方法可以根据传入对应参数的字节码来获取对应的构造方法;
Person person3 = (Person) con2.newInstance(100,"小张","男",23,"AB");//newInstance()方法通过传入具体参数来完成对象的创建;
System.out.println(person3);
Constructor<Person> con3[] = class2.getConstructors();//getConstructors()方法可以获取一个类的所有的重载的构造方法;
for(Constructor con4 : con3){
    System.out.println(con4.getName());
}

只有当要用某个类的无参构造方法创建该类对象时,可以省略创建Constructor类对象的这个过程。

Date d = (Date)Class.forName("java.util.Date").newINstance();

java运行环境的缓存中保存了类的无参构造方法所对应的Construtor对象。

 

Field类的基本概念:

Field类用来表示类中的属性(字段)。

  • Class.getFields() 得到Class对象的所有字段,返回的是Field数组。

  • Class.getField(String name) 返回一个Field对象,他反映此Class对象所表示的类或接口的指定公有成员字段。

  • Field的对象所代表的某一个类的属性,而不是那个类的某一个对象的属性。要得到某个对象的属性值,需要通过get(Object obj)方法与某个对象具体关联。

  • 对于非公有属性只能通过Class的getDeclaredField(String fieldName)方法得到。

  • 对于私有属性要得到它所关联的对象的值,需要通过Field的setAccessible(boolean boolean)方法设置。

  • Field类的getType()方法用来得到字段所属的类型。

Field类的基本使用:

Class class2 = Class.forName("com.zjb.ssm.reflect.Person");
Constructor con2 = class2.getConstructor(Integer.class,String.class,String.class,Integer.class,String.class);
//getConstructor()方法可以根据传入对应参数的字节码来获取对应的构造方法;
Person person3 = (Person) con2.newInstance(100,"小张","男",23,"AB");//创建对象
System.out.println(person3);
Constructor<Person> con3[] = class2.getConstructors();//getConstructors()方法可以获取一个类的所有的重载的构造方法;
for(Constructor con4 : con3){
    System.out.println(con4.getName());
}
Field fields[] = class2.getDeclaredFields();//获取所有属性;
for(Field f:fields){
    System.out.println("类型"+f.getType().getName()+",属性名称"+f.getName());
}
Field field = class2.getDeclaredField("name");//获取属性name;
field.setAccessible(true);//允许访问私有属性;
System.out.println(field.get(person3));//查看name字段在person3的取值;
for (Field f : fields) {
    if(f.getType()==String.class){//判断获得的类型是否是String类型;
        f.setAccessible(true);//允许访问私有属性;
        String oldValue = (String) f.get(person3);//获取旧的值
        String newValue = oldValue.concat("hello");//处理新值
        f.set(person3, newValue);//设置新值
    }
}
System.out.println(person3);

 运行结果:

Person{id=100, name='小张', sex='男', status=23, bloodType='AB'}
com.zjb.ssm.reflect.Person
com.zjb.ssm.reflect.Person
com.zjb.ssm.reflect.Person
com.zjb.ssm.reflect.Person
类型java.lang.Integer,属性名称id
类型java.lang.String,属性名称name
类型java.lang.String,属性名称sex
类型java.lang.Integer,属性名称status
类型java.lang.String,属性名称bloodType
小张
Person{id=100, name='小张hello', sex='男hello', status=23, bloodType='ABhello'}

Method的基本概念:

通过Class对象的如下方法得到Method对象:

Method getMethod(String name,Class<?>...parameterTypes)//按名称得到某个特定的public方法(包括从父类或接口继承的方法)

Method[] getMethods()//得到public方法(包括从父类或接口继承的方法)

Method[] getDeclaredMethod(String name,Class<?>...parameterTypes)//按名称得到某个特定的方法(不包括继承的方法)

Method[] getDeclaredMethods()//得到所有的方法(不包括继承方法) 

得到某个方法对应的Method对象后,需要调用如下方法来在某个对象上执行该方法:

invoke(Object obj,Oblect...obj)//方法用来调用Method所表示的方法。第一个参数表示此方法作用于哪个对象;如果调用的是一个静态方法,那么invoke()方法中第一个参数用null表示

 Method的基本操作:

Class class2 = Class.forName("com.zjb.ssm.reflect.Person");
Method methods[] = class2.getMethods();
for (Method m : methods) {
    System.out.println("捕获的方法:"+m.getName());
}
Method method = class2.getMethod("getName");
System.out.println(method.getName());
Method methods2[] = class2.getDeclaredMethods();
for (Method m : methods2) {
    System.out.println("捕获的方法:"+m.getName());
}
Method method1 = class2.getMethod("init",null);
System.out.println(method1.getName());
Method method2 = class1.getDeclaredMethod("message", String.class);
System.out.println("得到的这个方法是:"+method2.getName());
method2.setAccessible(true);//调用私有方法时要先设置可见性
method2.invoke(person3, "这是调用方法时的传递的实际参数");
Method method3 = class2.getMethod("showMessage", String.class);
System.out.println("得到的这个方法是:"+method3.getName());
method3.invoke(null, "这是调用静态方法时的传递的实际参数");
Method method4 = class2.getMethod("showMessages", String[].class);
System.out.println("得到的这个方法是:"+method4.getName());
method4.invoke(person3, new Object[] {new String[] {"你好","大大张","再见"}});//调用数组参数的方法时,把整个实际的数组作为一个Object数组的唯一元素进行调用;
method4.invoke(person3,(Object)new String[] {"你好","大大张","再见"});//把实际数组下转成Object对象;

运行结果:

捕获的方法:toString
捕获的方法:getName
捕获的方法:init
捕获的方法:setName
捕获的方法:getId
捕获的方法:getBloodType
捕获的方法:setStatus
捕获的方法:getStatus
捕获的方法:getSex
捕获的方法:setBloodType
捕获的方法:setId
捕获的方法:setSex
捕获的方法:showMessage
捕获的方法:wait  //线程等待的方法
捕获的方法:wait
捕获的方法:wait
捕获的方法:equals
捕获的方法:hashCode
捕获的方法:getClass
捕获的方法:notify
捕获的方法:notifyAll
getName
捕获的方法:toString
捕获的方法:getName
捕获的方法:init
捕获的方法:setName
捕获的方法:getId
捕获的方法:message
捕获的方法:getBloodType
捕获的方法:setStatus
捕获的方法:getStatus
捕获的方法:getSex
捕获的方法:setBloodType
捕获的方法:setId
捕获的方法:setSex
捕获的方法:showMessage
init
得到的这个方法是:message
这是调用方法时的传递的实际参数
得到的这个方法是:showMessage
这是调用静态方法时的传递的实际参数
得到的这个方法是:showMessages
你好
大大张
再见
你好
大大张
再见

Method类-关于方法参数的操作:

int getParameterCount()  //获取该对象Method对象所表示方法的参数数量。

Parameter[] getParameters()  //返回一个Parater对象数组,表示该Method对象所表示方法的所有参数。

Class<?>[] getParameterTypes()  //获取该Method对象所表示的所有参数类型的数组。

Type[] getGenericParameterTypes()  //获取该Method对象所表示方法的所有参数类型的数组,一般情况下,同getParameterTypes()方法的返回值一样,如果存在泛型,则该方法会返回泛型的类型。

Method类-关于修饰符

int getModifiers() //得到方法前面所定义的修饰符;

返回l类、接口、变量、方法等以整数编码的Java语言修饰符,访问修饰符编码列表。Modifier类一共提供了12种修饰符的编码表示常量。

java.lang.reflect.Modifier 类提供解码类和成员访问修饰符的静态方法和常量,修饰符集合被表示为具有表示不同的修饰符的不同位置的整数。

 

package com.zjb.ssm.reflect;


import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;


public class MyClass2 {
    int getInt(){
        int i = 0;
        return i;
    }
    private static Boolean getBoolean() {
        Boolean b = false;
        return b;
    }
    protected String getString() {
        String s = "";
        return s;
    }
    public Map<String,Object> getMap(){
        Map<String, Object> m = new HashMap<String, Object>();
        return m;
    }
    public static void main(String[] args) {
    Class<? extends MyClass2> aClass = MyClass2.class;
    Method[] methods = aClass.getDeclaredMethods();
    for (Method method : methods) {
        System.out.println("当前的方法名称是:"+method.getName());
        int i = method.getModifiers();
        System.out.println("当前的方法是否是public:"+ Modifier.isPublic(i));
        System.out.println("当前的方法是否是static:"+Modifier.isStatic(i));
        System.out.println("当前的方法是否是final:"+Modifier.isFinal(i));
        System.out.println("当前的方法是否是抽象方法:"+Modifier.isAbstract(i));
        System.out.println("当前的方法是否是静态方法:"+Modifier.isStatic(i));
        System.out.println("当前的方法是否是内部类:"+Modifier.isInterface(i));
        System.out.println("-------------------------------------------");
     }
    }
}
当前的方法名称是:getBoolean
当前的方法是否是public:false
当前的方法是否是static:true
当前的方法是否是final:false
当前的方法是否是抽象方法:false
当前的方法是否是静态方法:true
当前的方法是否是内部类:false
-------------------------------------------
当前的方法名称是:getInt
当前的方法是否是public:false
当前的方法是否是static:false
当前的方法是否是final:false
当前的方法是否是抽象方法:false
当前的方法是否是静态方法:false
当前的方法是否是内部类:false
-------------------------------------------
当前的方法名称是:getMap
当前的方法是否是public:true
当前的方法是否是static:false
当前的方法是否是final:false
当前的方法是否是抽象方法:false
当前的方法是否是静态方法:false
当前的方法是否是内部类:false
-------------------------------------------
当前的方法名称是:getString
当前的方法是否是public:false
当前的方法是否是static:false
当前的方法是否是final:false
当前的方法是否是抽象方法:false
当前的方法是否是静态方法:false
当前的方法是否是内部类:false
-----------------------------------------

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说好陪我数星星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值