Java 反射
2020-05-21 本文已影响0人
markeNick
定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
.
反射机制的相关类
这些类的主要方法和说明在文末
类名 | 说明 |
---|---|
Class类 | 获取类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 获取类的成员变量(成员变量也称为类的属性) |
Method类 | 获取类的方法 |
Constructor类 | 获取类的构造方法 |
.
动态创建对象和调用方法
public class Main {
public static void main(String[] args) {
Class c = Class.forName("User类路径");
// 通过Class类创建对象
User user_1 = (User) c.newInstance(); // 调用的是User类的无参构造方法
System.out.println(user_1);
// 通过构造器创建对象
Constructor constructor = c.getDeclaredConstructor(Integer.class, String.class);
User user_2 = (User) constructor.newInstance(1, "test");
System.out.println(user_2);
// 通过反射获取方法
User user_3 = c.newInstance(); // user:{id:1, name:"test"}
Method setName = c.getDeclaredMethod("setName", String.class);
setName.invoke(user_3, "testxxx");
System.out.println(user_3.getName())
// 通过反射操作属性
User user_4 = c.newInstance();
Field name = c.getDeclaredField("name");
name.setAccessible(true); // 属性私有需要取消安全监测
name.set(user_4, "testxxx");
System.out.println(user_4.getName());
}
}
class User {
private int id;
private String name;
public User(){
id = 1;
name = "test";
}
public User(int id, String name){
this.id = id;
this.name = name;
}
// ......省略 get/set 方法
// ......省略 toString 方法
}
.
反射操作泛型
Java一旦编译完成,所有和泛型有关的类型会全部被擦除,为了通过反射操作这些类型,Java新增了ParameterizedType
,GenericArrayType
,TypeVariable
和 WildcardType
几种类型来代表不能被归到Class类中的类型但是又和原始类型齐名的类型。
- ParameterizedType:表示一种参数化类型,比如Collection<String>
- GenericArrayType:表示一种元素类型是参数类型或者类型变量的数组类型
- TypeVariable :是各种类型变量的公共父接口
- WildcardType :代表一种通配符类型表达式
获取方法的形式参数的参数类型
public class Main {
public static void main(String[] args) throws NoSuchMethodException {
Method method = User.class.getMethod("test01", Map.class, List.class);
// 获得方法的形式参数的参数类型 ---- Map<String, User>
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type type : genericParameterTypes) {
System.out.println("type: " + type);
// 判断参数类型是否是一个参数化类型 ParameterizedType
if(type instanceof ParameterizedType) {
// 强制类型转换然后获得参数化类型的信息 ---- String, User
Type[] actualTypeArguments = ((ParameterizedType)type)
.getActualTypeArguments();
for (Type actualType : actualTypeArguments) {
System.out.println(actualType);
}
}
System.out.println("===========");
}
}
}
class User{
private Integer id;
private String name;
public void test01(Map<String, User> map, List<User> list){
System.out.println("test01");
}
public Map<String, User> test02() {
System.out.println("test02");
return null;
}
}
// 输出结果
type: java.util.Map<java.lang.String, com.trq.User>
class java.lang.String
class com.trq.User
===========
type: java.util.List<com.trq.User>
class com.trq.User
===========
.
获取方法的返回值的参数类型
与上面的区别就是返回值的参数类型只有一个,所以少了一层循环。
public class Main {
public static void main(String[] args) throws NoSuchMethodException {
Method method = User.class.getMethod("test02", null);
// 获取方法的返回值的参数类型 ---- Map<String, User>
Type genericParameterTypes = method.getGenericReturnType();
System.out.println("type: " + genericParameterTypes);
// 判断参数类型是否是一个参数化类型 ParameterizedType
if(genericParameterTypes instanceof ParameterizedType) {
// 强制类型转换然后获得参数化类型的信息 ---- String, User
Type[] actualTypeArguments = ((ParameterizedType) genericParameterTypes)
.getActualTypeArguments();
for (Type actualType : actualTypeArguments) {
System.out.println(actualType);
}
}
}
}
class User{
private Integer id;
private String name;
public void test01(Map<String, User> map, List<User> list){
System.out.println("test01");
}
public Map<String, User> test02() {
System.out.println("test02");
return null;
}
}
// 输出结果
type: java.util.Map<java.lang.String, com.trq.User>
class java.lang.String
class com.trq.User
.
反射获取注解信息
public class test3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException{
Class c = Class.forName("com.trq.User2");
// 获取注解的value值
TableName tableName = (TableName) c.getAnnotation(TableName.class);
System.out.println(tableName.value());
System.out.println("============");
// 获取类的指定的注解
Field field = c.getDeclaredField("name");
CheckColumn checkColume = field.getAnnotation(CheckColumn.class);
System.out.println(checkColume.columnName());
System.out.println(checkColume.type());
System.out.println(checkColume.length());
// 输出结果
user
============
name
varchar
32
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName {
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface CheckColumn {
String columnName();
String type();
int length();
}
@TableName("user")
class User2 {
@CheckColumn(columnName = "id", type = "int", length = 10)
private int id;
@CheckColumn(columnName = "name", type = "varchar", length = 32)
private String name;
public User2(int id, String name) {
this.id = id;
this.name = name;
}
}
.
反射机制的相关类的主要方法和说明
Class类
获得类信息的方法
方法 | 说明 |
---|---|
asSubclass(Class<U> clazz) | 把传递的类的对象转换成代表其子类的对象 |
Cast | 把对象转换成代表类或是接口的对象 |
getClassLoader() | 获得类的加载器 |
getClasses() | 返回一个数组,数组中包含该类中所有公共类和接口类的对象 |
getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 |
forName(String className) | 根据类名返回类的对象 |
getName() | 获得类的完整路径名字 |
newInstance() | 创建类的实例 |
getPackage() | 获得类的包 |
getSimpleName() | 获得类的名字 |
getSuperclass() | getSuperclass() |
getSuperclass() | 获得当前类实现的类或是接口 |
获得类中属性相关的方法
方法 | 说明 |
---|---|
getField(String name) | 获得某个public的属性对象 |
getFields() | 获得所有public的属性对象 |
getDeclaredField(String name) | 获得某个属性对象 |
getDeclaredFields() | 获得所有属性对象 |
获得类中注解相关的方法
方法 | 说明 |
---|---|
getAnnotation(Class<A> annotationClass) | 返回该类中与参数类型匹配的public注解对象 |
getAnnotations() | 返回该类所有的公有注解对象 |
getDeclaredAnnotation(Class<A> annotationClass) | 返回该类中与参数类型匹配的所有注解对象 |
getDeclaredAnnotations() | 返回该类所有的注解对象 |
获得类中构造器相关的方法
方法 | 说明 |
---|---|
getConstructor(Class...<?> parameterTypes) | 获得该类中与参数类型匹配的public构造方法 |
getConstructors() | 获得该类的所有public构造方法 |
getDeclaredConstructor(Class...<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
获得类中方法相关的方法
方法 | 说明 |
---|---|
getMethod(String name, Class...<?> parameterTypes) | 获得该类某个public的方法 |
getMethods() | 获得该类所有public的方法 |
getDeclaredMethod(String name, Class...<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法 |
其他重要的方法
方法 | 说明 |
---|---|
isAnnotation() | 如果是注解类型则返回true |
isAnnotationPresent(Class<? extends Annotation> annotationClass) | 如果是指定类型注解类型则返回true |
isAnonymousClass() | 如果是匿名类则返回true |
isArray() | 如果是一个数组类则返回true |
isEnum() | 如果是枚举类则返回true |
isInstance(Object obj) | 如果obj是该类的实例则返回true |
isInterface() | 如果是接口类则返回true |
isLocalClass() | 如果是局部类则返回true |
isMemberClass() | 如果是内部类则返回true |
.
Field类
方法 | 说明 |
---|---|
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Object obj, Object value) | 设置obj中对应属性值 |
.
Method类
方法 | 说明 |
---|---|
invoke(Object obj, Object... args) | 传递object对象及参数调用该对象对应的方法 |
.
Constructor类
方法 | 说明 |
---|---|
newInstance(Object... initargs) | 根据传递的参数创建类的对象 |