-------
android培训
、
java培训
、期待与您交流! ----------
反射的概念:
反射就是把Java类中的各种成分映射想成Java类。通过class文件的对象,获取构造函数、字段、方法的操作。
例如:众多的人用一个Person类表示,那么众多的Java类就用一个Class类表示。
反射也称之为对类的解剖。把类的各个组成部分映射成一个个相应的Java类。
学习反射的目的:
有些时候,可能JDK中的方法没有在帮助文档中提供,但是通过查看源代码,却发现有这个方法,不会该方法为private私有,所
以JDK的帮助文档没有提供该方法。如果必须使用这个方法,我们可以通过反射的方式来获取,进行使用。
得到某个class文件相对应的class对象的方法有3中:
1、getClass():返回进行时的类。
例如:new Date().getClass()。
2、数据类型.class:静态属性,来获取当前数据类型的自解码文件对象。
例如:Person.class.
3、public static Class forName(String className):返回与带有给定字符串名的类或接口相关联的Class对象。
例如:Class.forName("java.long.String");
代码示例:
注意:字节码文件是唯一的,无论怎么获取,都是同一份字节码文件。
Constructor类的实例化对象代表类的一个构造方法。
public Constructor[] getCOnstructors():反射所有的公共的构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造函数(包含私有)
public Constructor getContructor(Class<?>... parameterTypes):获取指定的构造函数
public Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):获取指定的构造函数(包含私有)
public void setAccessible(boolean flag):是否可以访问(暴力访问)
public Object newInstance(Object... initargs):使用此Constructor对象表示的构造方法来创建该构造方法的声明类的新实例,并用于指定的初始化该实例。
步骤:
a:创建一个Class字节码文件对象
b:获取指定的构造函数 如果是非public的构造函数,需要 强制访问(暴力访问)
c:创建对象
例如:
由结果可知:public Constructor[] getCOnstructors():反射所有的公共的构造方法 public Constructor[] getDeclaredConstructors():获取所有的构造函数(包含私有)
成员变量的反射(Field类):
Class中的方法:
public Field[] getFields() : 获取 public 修饰的 所有字段
public Field[] getDeclaredFields(): 获取所有的字段(包含私有)
public Field getField(String name): 获取指定的字段
public Field getDeclaredField(String name): 获取指定的字段(包含私有)
Field中的方法:
public void set(Object obj, Object value): 为指定对象中的当前字段, 赋值
步骤:
a: 创建class字节码文件对象
b: 获取指定的字段,如果是非public 修饰的字段, 需要 暴力访问
c: 对字段进行操作
举例验证上述方法:
public Method[] getMethods() 获取所有的公共方法(包含父类的)
public Method[] getDeclaredMethods() 获取所有的方法(不包含父类)
public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) : 获取指定的方法(包含私有的)
Method类的方法:
public Object invoke(Object obj, Object... args)
调用给定的对象中的当前方法,并且给定方法的参数列表,这个时候就可以确定调用的是具体的哪一个方法了
public void setAccessible(boolean flag)
步骤:
a: 创建class 字节码文件对象
b: 获取指定的方法
c: 使用方法(需要前有对象,才能使用方法)
举例验证上述方法:
反射就是把Java类中的各种成分映射想成Java类。通过class文件的对象,获取构造函数、字段、方法的操作。
例如:众多的人用一个Person类表示,那么众多的Java类就用一个Class类表示。
反射也称之为对类的解剖。把类的各个组成部分映射成一个个相应的Java类。
学习反射的目的:
有些时候,可能JDK中的方法没有在帮助文档中提供,但是通过查看源代码,却发现有这个方法,不会该方法为private私有,所
以JDK的帮助文档没有提供该方法。如果必须使用这个方法,我们可以通过反射的方式来获取,进行使用。
得到某个class文件相对应的class对象的方法有3中:
1、getClass():返回进行时的类。
例如:new Date().getClass()。
2、数据类型.class:静态属性,来获取当前数据类型的自解码文件对象。
例如:Person.class.
3、public static Class forName(String className):返回与带有给定字符串名的类或接口相关联的Class对象。
例如:Class.forName("java.long.String");
代码示例:
public class ClassTest {
public static void main(String[] args) throws ClassNotFoundException {
String s = "黑马";
//数据类型.class:静态属性,来获取当前数据类型的自解码文件对象,
Class c1 = String.class;
//getClass():返回进行时的类,
Class c2 = s.getClass();
//Class.forName(String className)返回与带有给定字符串名的类或接口相关联的Class对象。
Class c3 = Class.forName("java.lang.String");
System.out.println(c1 == c2);
System.out.println(c2 == c3);
}
}
注意:字节码文件是唯一的,无论怎么获取,都是同一份字节码文件。
public class Person {
private String name;
int age;
public String address;
public Person(){}
private Person(String name){
this.name = name;
}
Person(String name, int age){
this.name = name;
this.age = age;
}
public Person(String name, int age, String address){
this.name = name;
this.age = age;
this.address = address;
}
public void show(){
System.out.println("show");
}
public void method(String s){
System.out.println(s);
}
public String function(){
return "function";
}
public int sum (int x, int y) {
return x+y;
}
private void method(){
System.out.println("私有的method");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
构造方法的反射应用(Constructor类):Constructor类的实例化对象代表类的一个构造方法。
public Constructor[] getCOnstructors():反射所有的公共的构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造函数(包含私有)
public Constructor getContructor(Class<?>... parameterTypes):获取指定的构造函数
public Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):获取指定的构造函数(包含私有)
public void setAccessible(boolean flag):是否可以访问(暴力访问)
public Object newInstance(Object... initargs):使用此Constructor对象表示的构造方法来创建该构造方法的声明类的新实例,并用于指定的初始化该实例。
步骤:
a:创建一个Class字节码文件对象
b:获取指定的构造函数 如果是非public的构造函数,需要 强制访问(暴力访问)
c:创建对象
例如:
import java.lang.reflect.Constructor;
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//获取Person类的字节码文件对象
Class c = Class.forName("com.itheima_02.Person");
//public Constructor[] getConstructors()
Constructor[] cons = c.getConstructors();
for(Constructor con : cons){
System.out.println(con);
}
System.out.println("-----------------");
Constructor[] cons1 = c.getDeclaredConstructors();
for(Constructor con : cons1){
System.out.println(con);
}
}
}
其结果为:由结果可知:public Constructor[] getCOnstructors():反射所有的公共的构造方法 public Constructor[] getDeclaredConstructors():获取所有的构造函数(包含私有)
成员变量的反射(Field类):
Class中的方法:
public Field[] getFields() : 获取 public 修饰的 所有字段
public Field[] getDeclaredFields(): 获取所有的字段(包含私有)
public Field getField(String name): 获取指定的字段
public Field getDeclaredField(String name): 获取指定的字段(包含私有)
Field中的方法:
public void set(Object obj, Object value): 为指定对象中的当前字段, 赋值
步骤:
a: 创建class字节码文件对象
b: 获取指定的字段,如果是非public 修饰的字段, 需要 暴力访问
c: 对字段进行操作
举例验证上述方法:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo {
public static void main(String[] args) throws <span style="font-size:14px;"><span style="font-family:Simsun;"><span style="font-size:14px;"><span style="font-family:Simsun;"><span style="color:#330033;"><span style="LINE-HEIGHT: 21px"></span></span></span></span></span></span>Exception<span style="font-size:14px;"><span style="font-family:Simsun;"><span style="font-size:14px;"><span style="font-family:Simsun;"><span style="color:#330033;"><span style="LINE-HEIGHT: 21px"></span></span></span></span></span></span> {
// 创建class字节码文件对象
Class c = Class.forName("com.itheima_02.Person");
//创建构造函数并创建对象
Constructor con = c.getDeclaredConstructor();
Object obj = con.newInstance();// Person
//public Field[] getFields()
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("-------");
//public Field[] getDeclaredFields()
Field[] fields1 = c.getDeclaredFields();
for (Field field : fields1) {
System.out.println(field);
}
//public Field getField(String name): 获取指定的字段
Field addressField = c.getField("address");
System.out.println(obj);
//public void set(Object obj, Object value): 为指定对象中的当前字段, 赋值
addressField.set(obj, "北京");
//private String name;
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);//暴力访问
nameField.set(obj, "黑马");
System.out.println(obj);
}
}
其结果为:
成员方法的反射(Method类):
Class类中的方法:public Method[] getMethods() 获取所有的公共方法(包含父类的)
public Method[] getDeclaredMethods() 获取所有的方法(不包含父类)
public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) : 获取指定的方法(包含私有的)
Method类的方法:
public Object invoke(Object obj, Object... args)
调用给定的对象中的当前方法,并且给定方法的参数列表,这个时候就可以确定调用的是具体的哪一个方法了
public void setAccessible(boolean flag)
步骤:
a: 创建class 字节码文件对象
b: 获取指定的方法
c: 使用方法(需要前有对象,才能使用方法)
举例验证上述方法:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//创建class 字节码文件对象
Class c = Class.forName("com.itheima_02.Person");
//public Method[] getMethods() public
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("--------");
//public Method[] getDeclaredMethods() 所有的
Method[] methods1 = c.getDeclaredMethods();
for (Method method : methods1) {
System.out.println(method);
}
/*
* Person p = new Person();
* p.show();
*/
Constructor con = c.getConstructor();
Object obj = con.newInstance();// Person
//获取指定的方法
//public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法
Method showMethod = c.getMethod("show",null);
//System.out.println(showMethod);
//使用方法
//public Object invoke(Object obj, Object... args)
//调用给定的对象中的当前方法,并且给定方法的参数列表,这个时候就可以确定调用的是具体的哪一个方法了
showMethod.invoke(obj, null);
System.out.println("-----------------------------------------");
//public void method(String s){}
//public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法
Method meMethod = c.getMethod("method", String.class);
//public Object invoke(Object obj, Object... args)
meMethod.invoke(obj, "黑马");
System.out.println("-----------------------------------------");
//public String function(){}
Method functionMethod = c.getMethod("function", null);
String str = (String) functionMethod.invoke(obj,null);
System.out.println(str);
System.out.println("-----------------------------------------");
//public int sum (int x, int y) {}
Method sumMethod = c.getMethod("sum", int.class, int.class);
int sum = (int) sumMethod.invoke(obj, 22, 11);
System.out.println(sum);
System.out.println("-----------------------------------------");
//private void method(){}
//Method me2Method = c.getMethod("method", null);
Method me2Method = c.getDeclaredMethod("method", null);
//暴力点
me2Method.setAccessible(true);
me2Method.invoke(obj, null);
}
}
其结果为: