反射
Easy类
public class Easy {
public String name;
protected String code;//
String sex;
private String address;
static int maxage;
public static final transient String test = null;
public Easy() {}
public Easy(String name) {
this.name = name;
}
public void methodA(){
System.out.println("methodA");
}
public void methodB(int a, int b){
System.out.println("methodB");
System.out.println("嘻嘻"+a+","+b);
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public static int getMaxage() {
return maxage;
}
public static void setMaxage(int maxage) {
Easy.maxage = maxage;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("===setAddress===");
this.address = address;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
System.out.println("===setName===");
return name;
}
public void setName(String name) {
this.name = name;
}
}
Class类
有对象之前必须先有类,static来修饰类的属性。在Java中存储了类的内容,这个内容也应该是一个对像。Java中每一个类都有一个内存,这每一块内存都是一个对象,这些对象记录这些类中声明了哪些属性、方法,以及构造方法,Java将这些类抽象为Class类。
Class类的对象是不能通过‘new’获取的,我们通过以下三种方法获取类的对象
1.通过类名获取类对象
2.通过对象获取类对象
3.通过Class方法的forName方法获取类对象
public class EasyClassA {
public static void main(String[] args) throws ClassNotFoundException {
//Class类的对象是不能new的
//获取类的类对象
//通过类名获取类对象
Class clazz = EasyClassA.class;
//通过对象获取类对象
clazz = new EasyClassA().getClass();
//通过Class方法的forName方法获取类对象
clazz = Class.forName("类所在包名+类名");
System.out.println(clazz);
//类的类对象中存储了类中定义的内容 属性/方法/构造方法
}
}
类的类对象中存储了类中定义的内容(属性/方法/构造方法)。我们可以使用getField方法获取类中的属性:
import java.lang.reflect.Field;
public class EasyClassB {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
//获取类对象
Class c = Easy.class;
//类的类对象中存储了类中定义的内容 属性/方法/构造方法
/*获取类中的属性
java中用来记录 类的属性的类叫做Field
fName变量指向的对象就是Easy类中的name属性*/
Field fName = c.getField("name");
Easy easy=new Easy();
easy.name="张三";
System.out.println(easy.name);
//可以获取某一个Easy类的对象的name属性的值
Object objectName=fName.get(easy);
System.out.println(objectName);//"张三"
//注入该属性的值
fName.set(easy,"李四");
System.out.println(easy.name);//"李四"
}
}
getField、getFields只能获取类中的public声明的属性。因此,我们可以用getDeclaredField获取其他声明的属性,包括从父类继承来的属性。
此处getDeclaredField获取的private修饰的属性只是属性名,并不能获取属性的值,但是我们可以使用setAccessible(true)方法获得访问权限,这样我们就可以获取到private修饰的属性的值了
public class EasyClassB {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//获取类对象
Class c = Easy.class;
Easy easy=new Easy();
//getFiled getFields 只能获取类中public声明的属性
Field fCode=c.getDeclaredField("code");
//设置code属性的值
fCode.set(easy,"10001");
Object objCode=fCode.get(easy);//通过反射获取easy对象的code属性的值
System.out.println(objCode);
Field fSex=c.getDeclaredField("sex");
Field fAddress=c.getDeclaredField("address");
fSex.set(easy,"女");
//反射访问私有属性 必须先获取访问权限
fAddress.setAccessible(true);
fAddress.set(easy,"青岛");
System.out.println(fAddress.get(easy));
}
}
反射
反射是在程序运行期间可以动态获取类中定义的属性和方法以及构造方法的机制(思想)的实现。反射的核心是Class类,程序中使用的类,每一个类都有一个唯一对应的Class对象。
反射的API(接口):Field Method Constructor 反射会破坏类的封装性
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class EasyClassC {
public static <T> T getInstance(Class<T> tClass, Map values) throws InstantiationException, IllegalAccessException {
//通过反射获取实例 创建对象
T t = tClass.newInstance();//通过类中的无参构造方法创建对象
//通过反射获取类中定义的属性
Field[] farr=tClass.getDeclaredFields();
//System.out.println(Arrays.toString(farr));
for(Field fitem:farr){
//获取属性的名字
String fname=fitem.getName();//获取属性的名字
//获取该属性在Map中的键值对 属性对应的值
Object value=values.get(fname);
//设置属性访问权限
fitem.setAccessible(true);
fitem.set(t,value);
}
return t;
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Map map=new HashMap();
map.put("code","C1001");
map.put("name","李华");
map.put("sex","女");
Student stu = getInstance(Student.class,map);
System.out.println(stu);
}
}
class Student{
private String code;
private String name;
private String sex;
@Override
public String toString() {
return "Student{" +
"code='" + code + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
反射调用和使用类中的方法
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class EasyClassD {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//获取类对象
Class<Easy> c = Easy.class;
//反射获取方法 Method
Easy easy = c.newInstance();
//获取public方法
Method ma = c.getMethod("methodA");
//调用方法 对象.方法名() 面向对象
//method.invoke(对象) 反射
ma.invoke(easy);
Method mb = c.getMethod("methodB", int.class, int.class);
mb.invoke(easy,23,45);
}
}
内省
内省的底层是通过反射实现的。内省通过获取属性的读方法和写方法(getter/setter)来获取和设置属性的内容。内省不会破坏类的封装性。
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.util.Arrays;
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();
con = c.getConstructor(String.class);
con.newInstance("张三");
//修饰符 使用Modifier的方法判断方法/属性/构造方法的修饰符
Field f = c.getDeclaredField("test");
int fmod = f.getModifiers();
boolean bool= Modifier.isStatic(fmod);
System.out.println(bool);
// 获取BeanInfo
BeanInfo bi = Introspector.getBeanInfo(c);
//获取写的方法和读的方法 setter/getter
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
System.out.println(Arrays.toString(pds));
String pName = pds[0].getName();//获取属性的名字
System.out.println("属性名"+pName);
Method read = pds[0].getReadMethod();//对应属性的getter方法
Method write = pds[0].getWriteMethod();//对应的setter方法
//obj.setName("张三");//面向对象
//write.invoke(obj,"张三");//反射
Easy easy = c.newInstance();
write.invoke(easy,"张三");
}
}