-
用途:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
-
JAVA反射(放射)机制 :程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
/**
* 反射:就是通过.class文件对象,去使用该类的成员变量,构造方法,成员方法.
*
* Person p1=new Person();
* p1.使用;
* 这个就不是反射
* @author Administrator
*
*要这样使用就必须获得class文件对象,也就是得到class类对象.
*获取class类对象的方法
* 1.getClass();
* 2.数据类型的静态属性class
* 3.class类中的静态方法,className要是全限定名
* public static Class<?> forName(String className)
*选择那种方法;
* 自己随便,开发选择第三种,因为这种方式是一个字符串,而不是一个具体的类名,这样我们就可以把字串
*配置到配置文件中
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//方式一
Person p1 = new Person();
Class c1 = p1.getClass();
Person p2=new Person();
Class c2 = p2.getClass();
System.out.println(p1==p2);//false
System.out.println(c1==c2);//true
//方式二
Class c3=Person.class;
//int.class;
//String.class;
System.out.println(c3==c2);//true;
//方式三,
Class c4=Class.forName("day13.Person");
System.out.println(c4==c3);
}
}
反射是框架设计的灵魂:
1.通过反射获取成员变量并使用:
public class Reflect1 {
public static void main(String[] args) throws Exception{
//获取字节码对象
Class c=Class.forName("day13.Person");
/*//获取所有成员变量
java.lang.reflect.Field[] fields=c.getDeclaredFields();
for (java.lang.reflect.Field field : fields) {
System.out.println(field);
}*/
//通过无参构造方法创建对象
Constructor cons = c.getConstructor();
Object obj=cons.newInstance();
//获取单个成员变量
//并对其赋值
java.lang.reflect.Field addressFiled=c.getField("address");
addressFiled.set(obj, "北京");//给obj对象的addressFiled设置值.
System.out.println(obj);
}
}
Person类:
public class Person {
private String name;
private int age;
public String address;
//构造方法
public Person(){
}
//成员方法
Person(String name,Integer 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("method"+s);
}
public String method(String s,int i){
return s+"---"+i;
}
private void function(){
System.out.println("function");
}
2.通过反射获取无参构造方法:
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
//获取字节码对象
Class c=Class.forName("day13.Person");
//获取构造方法
//public Constructor[] getConstructors(),获取的是public修饰的构造方法
//public Constructor[] getDeclaredConstructors()返回所有
/*Constructor[] cons=c.getDeclaredConstructors();
for (Constructor constructor : cons) {
System.out.println(constructor);
}*/
//获取单个构造方法
Constructor cons=c.getConstructor();
Object obj=cons.newInstance();
System.out.println(obj);
}
}
2.通过反射获取有参构造方法:
public static void main(String[] args) throws Exception{
//获取字节码对象
Class c=Class.forName("day13.Person");
//获取带参构造参数
//public Constructor getConstructor(Class<?>... parameterTypes)
Constructor con = c.getConstructor(String.class,int.class,String.class);
//通过带参构造方法对象创建对象
//public T newInstance(Object... initargs)
Object obj=con.newInstance("海燕",23,"成都");
System.out.println(obj);
}
}
3.通过放射获取私有构造方法(加一个Declared):
public class ReflectDemo3 {
public static void main(String[] args) throws Exception{
//获取字节码对象
Class c=Class.forName("day13.Person");
//获取带参构造函数
Constructor cons = c.getDeclaredConstructor(String.class,Integer.class);
cons.setAccessible(true);//值为 true则指示反射的对象在使用时应该取消 Java语言访问检查
Object obj=cons.newInstance("海燕",23);
System.out.println(obj);
}
}
4.通过放射获取成员变量并调用
package fanshe.field;
import java.lang.reflect.Field;
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* package fanshe.field;
import java.lang.reflect.Field;
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*
*/
public class Fields {
public static void main(String[] args) throws Exception {
//1.获取Class对象
Class stuClass = Class.forName("fanshe.field.Student");
//2.获取字段
System.out.println("************获取所有公有的字段********************");
Field[] fieldArray = stuClass.getFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
fieldArray = stuClass.getDeclaredFields(); for(Field f : fieldArray){ System.out.println(f); } System.out.println("*************获取公有字段**并调用***********************************"); Field f = stuClass.getField("name"); System.out.println(f); //获取一个对象 Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student stu = new Student(); //为字段设置值 f.set(obj, "刘德华");//为Student对象中的name属性赋值--》stu.name = "刘德华" //验证 Student stu = (Student)obj; System.out.println("验证姓名:" + stu.name); System.out.println("**************获取私有字段****并调用********************************"); f = stuClass.getDeclaredField("phoneNum"); System.out.println(f); f.setAccessible(true);//暴力反射,解除私有限定 f.set(obj, "18888889999"); System.out.println("验证电话:" + stu); } }
对应的student类
package fanshe.field;
public class Student {
public Student(){
}
//**********字段*************//
public String name;
protected int age;
char sex;
private String phoneNum;
反射方法的其它使用之---通过反射越过泛型检查
泛型用在编译期,编译过后泛型擦除(消失掉)。所以是可以通过反射越过泛型检查的 ,其实也就是在.class文件中没有泛型的概念的.
public static void main(String[] args) throws Exception{
ArrayList<String> strList = new ArrayList<>();
strList.add("aaa");
strList.add("bbb");
// strList.add(100);
//获取ArrayList的Class对象,反向的调用add()方法,添加数据
Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
//获取add()方法
Method m = listClass.getMethod("add", Object.class);
//调用add()方法
m.invoke(strList, 100);
//遍历集合
for(Object obj : strList){
System.out.println(obj);
}
}
学习反射必须明白类加载:
启动(Bootstrap)类加载器:java中jre中的类.
扩展(Extension)类加载器:java扩展的api类ext好像是
系统(System)类加载器:自己写的类
https://www.2cto.com/uploadfile/Collfiles/20160126/2016012609242889.jpg