Table of Contents
1.4:Class对象.getSuperclass()获取到父类
1:.getDeclaredConstructors():获取所有的构造方法
1:getDeclaredMethods():获取所有的方法对象,包括私有的和实现接口的,但不包括父类的;
3:.getMethod():获取public的方法包括父类的和实现接口的
相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有个开源框架jOOR相信很多人都用过,不过我们还是要学习反射的基础语法,这样才能自己写出优秀的框架,当然这里所讲的反射技术,是学习Android插件化技术、Hook技术等必不可少的!
1:创建Class
1.1: getClass方法
String str = "Hello";
Class aClass = str.getClass();
System.out.println(""+aClass.getName());//java.lang.String
User user = new User();
Class calss2 = user.getClass();
System.out.println(""+calss2.getName());//com.wkl.bean.User
1.2:Class.forName
try {
//这里也通过捕获异常,因为我们传的这个字符串可能不合法,字符串合法命名是类的命名空间和类的名称组成
Class<?> aClass = Class.forName("java.lang.String");
System.out.println(""+aClass.getName());//java.lang.String
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
1.3:类名.class
Class<User> userClass = User.class;
System.out.println(""+userClass.getName());//com.wkl.bean.User
1.4:Class对象.getSuperclass()获取到父类
Class<?> aClass = Class.forName("java.lang.String");
System.out.println(""+aClass.getName());//java.lang.String
String name = aClass.getSuperclass().getName();
System.out.println(""+name);//java.lang.Object
2:获取构造方法
当类中方法定义为私有的时候我们能调用?不能!当变量是私有的时候我们能获取吗?不能!但是反射可以,比如源码中有你需要用到的方法,但是那个方法是私有的,这个时候你就可以通过反射去执行这个私有方法,并且获取私有变量。
public class User {
private String name;
private int age;
private String sex;
public User(String name) {
this.name = name;
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
private User(int age) {
this.age = age;
}
}
1:.getDeclaredConstructors():获取所有的构造方法
Class<User> userClass = User.class;
Constructor<?>[] constructors = userClass.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
System.out.println("构造器名称:"+constructor.getName());
System.out.println("修饰符类型:"+constructor.getModifiers());
Parameter[] parameters = constructor.getParameters();
System.out.println("构造器参数:"+ JSONArray.toJSONString(parameters));
Class<?>[] parameterTypes = constructor.getParameterTypes();
System.out.println("构造器参数类型:"+ JSONArray.toJSONString(parameterTypes));
System.out.println("=====================================================");
}
2:getConstructors():获取共有的构造方法
其余的和上边一样
3:获取特定的构造方法
我们可以通过getDeclaredConstructor()方法传参获取特定参数类型的构造方法,
这里注意是getDeclaredConstructor()不是 getDeclaredConstructors() ,所以返回的是一个Class对象而不是一个Class数组。
Class<User> userClass = User.class;
try {
Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class);
System.out.println(""+declaredConstructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
不传参数,默认取无参构造方法
4:利用构造方法反射创建对象
Class<User> userClass = User.class;
try {
Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class);
System.out.println(""+declaredConstructor);
User user = declaredConstructor.newInstance("123");
System.out.println(""+user);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
结果:
5:调用类的私有构造方法
调用私有构造方法呢,和上面一样,只是我们要设置constructors.setAccessible(true);
3:对类中方法的操作
1:getDeclaredMethods():获取所有的方法对象,包括私有的和实现接口的,但不包括父类的;
Class<User> userClass = User.class;
Method[] declaredMethods = userClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("方法名:"+declaredMethod.getName());
System.out.println("修饰符"+declaredMethod.getModifiers());
System.out.println("参数类型:"+JSONArray.toJSONString(declaredMethod.getParameterTypes()));
System.out.println("返回类型:"+declaredMethod.getReturnType());
System.out.println("================");
}
方法名:toString
修饰符1
参数类型:[]
返回类型:class java.lang.String
================
方法名:moth2
修饰符2
参数类型:[]
返回类型:class java.lang.String
================
方法名:moth1
修饰符1
参数类型:[]
返回类型:class java.lang.String
================
2:getDeclaredMethod():获取指定方法
第一个参数是方法名,第二个参数是参数类型
Class<User> userClass = User.class;
try {
//第一个参数是方法名,第二个参数是参数类型
Method meth1 = userClass.getDeclaredMethod("moth1",String.class);
System.out.println(""+ JSONObject.toJSONString(meth1));
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
3:.getMethod():获取public的方法包括父类的和实现接口的
Method meth1 = userClass.getMethod("moth1",String.class);
4:meth1.invoke():指定特定的方法
invoke需要两个参数一个是类的实例,一个是方法参数。
Class<User> userClass = User.class;
try {
User user = new User("aa");
//第一个参数是方法名,第二个参数是参数类型
Method meth1 = userClass.getDeclaredMethod("moth1",String.class);
Object wkl = meth1.invoke(user, "wkl");
System.out.println(""+wkl);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
wkl:moth1
4:通过Field类,为对象设置字段值
Class<User> userClass = User.class;
Field name = userClass.getDeclaredField("name");
User user = userClass.newInstance();
//因为属性是私有的,所以需要设置Accessible
name.setAccessible(true);
name.set(user,"wkl");
System.out.println(""+user);
User{name='wkl', age=0, sex='null'}