1.反射
创建对象的四种方式:new ,clone,反序列化,反射
1.反射定义
反射就是在程序运行期间,可以动态获取类中定义的属性和方法,以及构造方法的机制(思想)的实现
反射的核心是Class类,程序中使用的类,每一个都有一个唯一对应的Class对象
反射的api就是Field Method Constructor
反射会破坏类的封装(要通过场景说明)
2.原理
有对象之前必须先有类 static来修饰类或方法
在java中存储了类的内容,这个内容也应该是对象
java中每一个类都有一个内存,这每一块内存都是一个对象
这些对象记录了这些类当中声明了哪些属性和方法以及构造方法
java将这些类抽象为Class类
注意!!!
Class类的对象是不能new的
3.获取类的对象有三种方式:
1.类.class
2.对象.getclass
3.Class.forName
public static void main(String[] args) {
//Class类的对象是不能new的
//获取类的类对象
//1.通过类名获取类对象
Class clazz= EasyClassA.class;
System.out.println(clazz);
//2.通过对象获得类对象
clazz=new EasyClassA().getClass();
System.out.println(clazz);
//3.通过class方法的forName方法获取
try {
clazz=Class.forName("com.situ.chapter725.EasyCorlor");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
System.out.println(clazz);
//类的类对象中存储了类中定义的内容 : 属性/方法/构造方法
}
4.使用反射实例
实例1
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//类的类对象中存储了类的属性,方法,构造方法
//获取内容:获取类中的属性
Class c=Easy.class;//获取类对象
c=new Easy().getClass();//获取类对象
try {
c=Class.forName("com.situ.chapter726.Easy");//获取类对象
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
///上面三种方式都可以获取类的类对象
//java中用来记录 类的属性 的类叫Filed
c.getField("name");
Field flname=c.getField("name");
//可以获取某一个Easy的对象的name属性的值
Easy easy=new Easy();
easy.name="zhangsan";
System.out.println(easy.name);
//Flname指向的对象就是Easy类中的name属性
Object objName= flname.get(easy);
System.out.println(objName);
//注入该属性的值
flname.set(easy,"lisi");
System.out.println(easy.name);
//Field fCode=c.getField("code");//getFiled getFiles只能获取类中public声明的属性所以需要使用getDeclaredFiled()方法
Field fCode=c.getDeclaredField("code");
fCode.set(easy,"1000");
fCode.get(easy);//通过反射获取Easy对象的属性的值
Object objCode=fCode.get(easy);
System.out.println(objCode);
Field fSex=c.getDeclaredField("sex");
Field fAddress=c.getDeclaredField("address");
fSex.set(easy,"nan");
//fAddress.set(easy,"我的"); //会报错IllegalAccessException
//反射可以获取私有属性,必须先获取访问权限
fAddress.setAccessible(true);//
fAddress.set(easy,"我的"); //现在就可以使用了
System.out.println(fSex.get(easy));
System.out.println(fAddress.get(easy));
System.out.println(easy);
}
实例2
实现将HAshMap中的数据通过反射获取出来(不知道此时都有什么属性)
public class EasyClassC {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
HashMap map=new HashMap<>();
map.put("code","C1001");
map.put("name","张三");
map.put("sex","女");
Student stu=getinstance(Student.class,map);
System.out.println(stu);
}
public static <T>T getinstance(Class<T> tClass, HashMap values) throws InstantiationException, IllegalAccessException {
//通过反射获取实例
T t= tClass.newInstance();//通过类中的无参构造方法创建对象
//通过反射获取类中定义的属性
Field[] arr=tClass.getDeclaredFields();
System.out.println(Arrays.toString(arr));
for (Field fitem:arr){
//获取属性的名字
String fName=fitem.getName();
//获取该属性在map中的键值对 属性对应的值
Object value=values.get(fName);
//设置属性访问权限
fitem.setAccessible(true);
//注入
fitem.set(t,value);
}
return t;
}
}
class Student {
private String code;
private String name;
private String sex;
@Override
public String toString() {
return "Student{" +
"code='" + code + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
5.反射获取方法
public class EasyClassD {
public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//获取类对象
Class<Easy> c=Easy.class;//确定c是Easy的类对象
//反射获取方法 Method
Method methodA=c.getMethod("methodA");//只能获取public方法,想用其他权限的和属性用法一样
Easy easy=c.newInstance();
//调用方法 原来:对象.方法名() 反射:方法名.invoke(对象)
methodA.invoke(easy);
Method method=c.getMethod("menthodB", int.class, int.class);
method.invoke(easy,23,45);
}
}
6.反射获取构造方法
public class EasyClassE {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IntrospectionException {
//反射获取构造方法
Class<Easy> c=Easy.class;
c.newInstance();//调用无参构造方法
//获取无参构造方法
Constructor<Easy> con=c.getConstructor();
con.newInstance();
c.getConstructor(String.class);
//con.newInstance("张三");
//修饰符 用Modifiers()方法判断方法属性或构造方法的修饰符是什么
Field field=c.getDeclaredField("test");
int fot=field.getModifiers();
boolean b=Modifier.isStatic(fot);
System.out.println(b);
//内省 通过反射实现但是不会破坏封装性
//获取bininfo
BeanInfo br=Introspector.getBeanInfo(c);
//获取BeanInfo中写的方法和读的方法
PropertyDescriptor[] de=br.getPropertyDescriptors();
System.out.println(Arrays.toString(de));
String name=de[0].getName();//获取属性的名字
System.out.println("属性名为"+name);
Method read=de[0].getReadMethod();//获得该属性对应属性的get方法
Method write=de[0].getWriteMethod();//获得该属性对应属性的set方法
//以前:obj.setName(“张三”);(面向对象)
//反射:write.invoke(obj,"张三")
Easy easy=c.newInstance();
write.invoke(easy,"张三");
}
}
JAVAse基本结束