对于一个类来说,最重要的是什么?
构造+属性+方法+访问权限
待测试的类
/**
* 作者:张风捷特烈
* 时间:2018/5/6:10:40
* 邮箱:1981462002@qq.com
* 说明:反射测试类
*/
public class Person {
private int age;
private String name;
private boolean isMan;
public String address="beijing";
public Person() {
System.out.println("空参构造执行...");
}
public Person( String name, int age,boolean isMan) {
this.age = age;
this.name = name;
this.isMan = isMan;
System.out.println("三参构造执行...");
}
public void publicShow() {
System.out.println("I am " + name + ",I " + age + "years");
}
public static void staticShow() {
System.out.println("staticShow");
}
private void privateShow() {
System.out.println("I am " + name + ",I " + age + "years");
}
public void paramShow(String str,int num) {
System.out.println("I am " + str + ",I " + num + "years");
}
}
一、拿到Class对象
Class对象是什么?
Class是一个类,而且它只有一个私有的构造函数,说明它不能通过new来获取对象,构造函数传入一个ClassLoader。
每个类被加载进入内存之后,系统就会为该类生成一个对应的java.lang.Class对象,
通过该Class对象就可以访问到JVM中的这个类,就可以获取某类的一切
private Class(ClassLoader loader) {
// Initialize final field for classLoader. The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
}
1.对象.getClass()获取Class对象
前提:已存在对象,未知该类全貌,可以使用此方法获取Class对象来探测该类
Object类中有一个native方法获取Class
public final native Class<?> getClass();
public static void getClass_1() {
Person person = new Person();
Class<? extends Person> personClass = person.getClass();
}
2.类名.class获取Class对象
前提:需要已知类名
public static void getClass_2() {
Class<Person> personClass = Person.class;
}
3.通过指定字符串:获取Class对象
前提:需已知全类名
public static void getClass_3() {
try {
Class<?> person = Class.forName("top.toly.bean.Person");
System.out.println(person);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
二、通过反射构造对象
1.获取无参构造实例化对象:clazz.newInstance()
/**
* 通过反射建无参实例
*/
public static void createInstance() {
//早期:new 的时候,先根据类名寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
// 再创建该字节码文件对相应的Person对象
try {
String className = "top.toly.bean.Person";
// 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
System.out.println(instance instanceof Person);//true
} catch (Exception e) {
e.printStackTrace();
}
2.通过反射建有参实例:clazz.getConstructor
/**
* 通过反射建有参实例
*/
private static void createInstance_2() {
try {
String className = "top.toly.bean.Person";
// 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
Class<?> clazz = Class.forName(className);
Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
Object instance = constructor.newInstance("捷特", 24, true);
System.out.println(instance);
//Person{age=24, name='捷特', isMan=true, address='beijing'}
} catch (Exception e) {
e.printStackTrace();
}
}
补充:XXXDeclaredXXX都是只获取本类,不包括父类
// 获得该类所有的构造器,不包括其父类的构造器
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
// 获得该类所以public构造器,包括父类
public Constructor<T> getConstructor(Class<?>... parameterTypes)
三、通过反射获取字段
1.获取公共字段:clazz.getField
/**
* 获取公共字段
*/
public static void getPublicField() throws Exception {
String className = "top.toly.bean.Person";
// 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
Class<?> clazz = Class.forName(className);
Field address = clazz.getField("address");//获取公有字段
Object o = address.get(clazz.newInstance());
System.out.println(o);//beijing
}
2.获取私有字段:
/**
* 获取私有字段
*/
public static void getPrivateField() throws Exception {
String className = "top.toly.bean.Person";
// 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
Class<?> clazz = Class.forName(className);
Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
Object instance = constructor.newInstance("捷特", 24, true);
//可以获取所有类型字段
Field name = clazz.getDeclaredField("age");
//想要访问私有,需要将可获取置为true
name.setAccessible(true);
//设置私有成员值
name.setInt(instance,30);
//获取私有成员值
Object o = name.get(instance);
System.out.println(o);//30
}
四、调用方法:
1.获取公共方法:getMethods()
/**
* 获取公共方法
*/
public static void getPublicMethod() throws Exception {
String className = "top.toly.bean.Person";
// 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
Class<?> clazz = Class.forName(className);
//创建实例
Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
Object instance = constructor.newInstance("捷特", 24, true);
Method[] methods = clazz.getMethods();//只能获取公有方法,包括父类
for (Method m : methods) {
System.out.println(m);
}
//获取公共无参
Method publicShow = clazz.getMethod("publicShow", null);
//调用函数:invoke
publicShow.invoke(instance, null);
//获取公共有参
Method paramShow = clazz.getMethod("paramShow", String.class, int.class);
paramShow.invoke(instance, "龙少", 24);
}
clazz.getDeclaredMethod:获取指定名称和参数类型的本类中声明(访问权限不限)的方法 clazz.getDeclaredMethods(): 获取该类所有的方法,不包括父类 clazz.getMethod:获取当前类及所有继承的父类的public修饰的方法。仅包括public clazz.getMethods();获取该类所有的public方法,包括父类的
2.获取私有方法:getDeclaredMethods()
/**
* 获取私有方法
*/
public static void getPrivateMethod() throws Exception {
String className = "top.toly.bean.Person";
// 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
Class<?> clazz = Class.forName(className);
Method[] declaredMethods = clazz.getDeclaredMethods();//获取该类中的所有方法
//创建实例
Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
Object instance = constructor.newInstance("捷特", 24, true);
for (Method m : declaredMethods) {
System.out.println(m);
}
Method privateShow = clazz.getDeclaredMethod("privateShow", null);
privateShow.setAccessible(true);
privateShow.invoke(instance,null);
}
反射差不多也就这些,理论并不难,学以致用才是关键
后记、
1.声明:
[1]本文由张风捷特烈原创,转载请注明 [2]欢迎广大编程爱好者共同交流 [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 [4]你的喜欢与支持将是我最大的动力
2.连接传送门:
更多安卓技术欢迎访问:安卓技术栈 我的github地址:欢迎star 简书首发,腾讯云+社区同步更新 张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com
3.联系我
QQ:1981462002 邮箱:1981462002@qq.com 微信:zdl1994328
4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
公众号.jpg
转载于:https://www.cnblogs.com/toly-top/p/9781884.html