概念:反射就是把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
-----------------------------------------