Java反射以及应用
需求:需要通过反射动态获取类的字段类型,然后做特殊处理
Java反射getDeclaredField和getField的区别
getDeclaredFiled 只能获取类本身的属性成员(包括私有、共有、保护)
getField 仅能获取类(及其父类可以自己测试) public属性成员
反射获取所有的字段
[code]Class clazz = 类.class; Field[] fields= classzz.getDeclaredFields();
获得某个具体字段,并获取类型
[code]String fieldType=clazz.getDeclaredField("需要获取的字段").getType().toString(); if(fieldType.contains("Integer")||fieldType.contains("Long")){ //这里做业务处理 }
下面再看一个完整的例子:
[code]public class User { public String name; public int age; public String address; }
[code]public static void getFieldsValue(Object obj) { Field[] fields = obj.getClass().getDeclaredFields(); /** * 基本类型、包装类型、String类型 */ String[] types = {"java.lang.Integer", "java.lang.Double", "java.lang.Float", "java.lang.Long", "java.lang.Short", "java.lang.Byte", "java.lang.Boolean", "java.lang.Character", "java.lang.String", "int","double","long","short","byte","boolean","char","float"}; for(Field f : fields){ f.setAccessible(true); try { for(String str : types) { if(f.getType().getName().equals(str)) System.out.println("字段:"+f.getName()+" 类型:"+f.getType().getName()+" 值:"+ f.get(obj)); } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
获取更多类型方法:
Java-使用反射获取类型信息:https://blog.csdn.net/alisonyu/article/details/82762765
数组类型
数组类型不像其他的类型可以通过isAssignableFrom()函数来进行判断,他需要使用isArray() 来判断该type是否是一个数组类型,然后使用getComponentType() 获取他的元素的类型
[code]public void queryArrayType() throws NoSuchFieldException { Field field = Some.class.getDeclaredField("具体字段"); Class<?> type = field.getType(); //一般来说,判断是否是某种类型是可以使用isAssignableFrom // 判断是否是数组类型比较特殊,要使用isArray()这个函数 if (type.isArray()){ //获得数组的类型,使用getComponentType()这个方法 Class<?> componentType = type.getComponentType(); assertEquals(componentType,Integer.class); } else{ throw new IllegalStateException(); } }
带泛型的类型
ParameterizedType表示参数化的类型,例如Collection这样的类型。我们可以通过getGenericType()方法获得该子类,当你的类型带有参数的时候就会返回ParameterizedType,否则会返回普通的类型(class)
[code]public void getListType() throws NoSuchFieldException { Field field = Some.class.getDeclaredField("list"); //如果类似于List<String>这样的类型就是一种GenericType //注意这是一种Type类型 Type type = field.getGenericType(); if (type instanceof ParameterizedType){ //泛型参数类型 ParameterizedType parameterizedType = (ParameterizedType)type; Type[] actualTypes = parameterizedType.getActualTypeArguments(); //因为List<String>获得第一个泛型参数,因为只有一个,我们取第一个 //如果我们有多个泛型参数,我们可以根据顺序取不同的泛型参数 assertEquals(actualTypes[0],String.class); //如果获得List这个原始类型呢? assertEquals(parameterizedType.getRawType(),List.class); }else{ throw new IllegalStateException(); } }
下面是我以前写的关于反射的笔记,如果有对反射基础知识不清楚的需要补课:
说明:
Class这个Java类保存的是一个Java类的meta信息(元信息)。一般在反射中使用。
Object类,是所有Java类的根。包括Class类。
Class类:用于描述一切类/接口.枚举是一种类,注解是一种接口
Class实例:就是指JVM中一份字节码
Class类:用于描述一切类/接口.问题:那Class实例到底表示的是哪一份字节码,为了明确区分出Class实例表示的是谁的字节码.Class类提供了泛型
Class<Date> clz1 = Date.class;//clz1表示是Date的字节码
Class<String> clz2 = String.class;//clz2表示的是String的字节码
如何得到Class的实例:
1.类名.class(就是一份字节码)
2.Class.forName(String className);根据一个类的全限定名来构建Class对象
3.每一个对象多有getClass()方法:obj.getClass();返回对象的真实类型
一个类在JVM中只有一份字节码;
第一种方式:数据类型.class
Class<User> clz1 = User.class;
第二种方式: Class.forName(String className);
Class<?> clz2 = Class.forName("cn.itcast.cd.User");
使用?是因为此时Class不知道类,因为传的是字符串
反射很强大,但是耗性能.主要是为了做工具和框架使用的.
第三种方式: 对象.getClass();得到对象的真实类型,每个方法都有所以在Object里
User u = new User();
Class clz3 = u.getClass();
clz1 == clz2 == clz3:因为表示都是JVM中共同的一份字节码(User.class)
new一个类才会把字节码从IO加载到内存。
Java内置9大的Class实例
对于对象来说,可以直接使用对象.getClass()或者Class.forName(className); 类名.class都可以获取Class实例.
但是我们的基本数据类型,就没有类的权限定名,也没有getClass方法.
问题:那么如何使用Class类来表示基本数据类型的Class实例?
byte,short,int,long,char,float,double,boolean ,void关键字
上述8种类型和void关键字,都有class属性.
表示int的Class对象: Class clz = int.class;
表示boolean的Class对象: boolean.class;
void: Class clz = void.class;
所有的数据类型都有class属性,表示都是Class对象.
思考:
int的包装类是Integer
Integer.class ==?== int.class
结果是false,说明是两份字节码.
Integer 和int是同一种数据类型吗? 不是
但是在八大基本数据类型的包装类中都有一个常量:TYPE
TYPE表示的是该包装类对应的基本数据类型的Class实例.
如:Integer.TYPE----->int.class
Integer.TYPE==int.class;//YES
Integer.TYPE == Integer.class;//ERROR
数组的Class实例:
String[] sArr1 = {"A","C"};
String[] sArr2 = {};
String[][] sArr = {};
int[] sArr = {};
表示数组的Class实例:
String[] sArr1 = {"A","C"};
Class clz = String[].class;//此时clz表示就是一个String类型的一位数组类型
所有具有相同元素类型和维数的数组才共享同一份字节码(Class对象);
注意:和数组中的元素没有一点关系.
获取类中的构造器
获取某一个类中的所有的构造器:
1,明确操作的是哪一份字节码对象
2,获取构造器
Class类获取构造器方法:
Constructor类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器
public Constructor<?>[] getConstructors():该方法只能获取当前Class所表示类的public修饰的构造器
public Constructor<?>[] getDeclaredConstructors():获取当前Class所表示类的所有的构造器,和访问权限无关
public Constructor<T> getConstructor(Class<?>... parameterTypes) :获取当前Class所表示类中指定的一个public的构造器
参数:parameterTypes表示:构造器参数的Class类型
如:public User(String name)
Constructor c = clz.getConstructor(String.class);
[code]public class User { public User(){}; public User(String name){}; public User(String name,String school){}; }
[code] System.out.println(Integer.TYPE); Class<User> clz=User.class; Constructor[]cs=clz.getConstructors(); for (Constructor c : cs) { System.out.println(c); } //获取单个构造器 Constructor c=clz.getDeclaredConstructor(String.class); System.out.println(c);
调用构造器,创建对象
Constructor<T>类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器
常用方法:
public T newInstance(Object... initargs):如调用带参数的构造器,只能使用该方式.
参数:initargs:表示调用构造器的实际参数
返回:返回创建的实例,T表示Class所表示类的类型
如果:一个类中的构造器可以直接访问,同时没有参数.,那么可以直接使用Class类中的newInstance方法创建对象.
public Object newInstance():相当于new 类名();
修改User
[code]public class User { public User() { System.out.println("---"); } public User(String name) { System.out.println(name); } public User(String name, String school) { System.out.println(name + " " + school); } }
[code]public static void main(String[] args) throws Exception { System.out.println(Integer.TYPE); Class<User> clz=User.class; Constructor[]cs=clz.getConstructors(); for (Constructor c : cs) { System.out.println(c); } //获取单个构造器 //泛型 Constructor<User> c=clz.getDeclaredConstructor(String.class); System.out.println(c); User u=c.newInstance("abc"); //不带泛型 Constructor c2=clz.getDeclaredConstructor(String.class); System.out.println(c2); Object u2=c2.newInstance("abc"); }
Class.forName方式
如果访问不带参数的构造器可以直接用Class的newInstance()方法
修改访问权限为private
[code]public class User { public User() { System.out.println("---"); } private User(String name) { System.out.println(name); } public User(String name, String school) { System.out.println(name + " " + school); } }
报错
[code]Constructor<User> c=clz.getDeclaredConstructor(String.class); System.out.println(c); c.setAccessible(true); User u=c.newInstance("abc");
获取类中的方法
使用反射获取某一个类中的方法:
1.找到获取方法所在类的字节码对象
2.找到需要被获取的方法
Class类中常用方法:
public Method[] getMethods():获取包括自身和继承过来的所有的public方法
public Method[] getDeclaredMethods():获取自身所有的方法(不包括继承的,和访问权限无关)
public Method getMethod(String methodName,
Class<?>... parameterTypes):表示调用指定的一个公共的方法(包括继承的)
参数:
methodName: 表示被调用方法的名字
parameterTypes:表示被调用方法的参数的Class类型如String.class
public Method getDeclaredMethod(String name,
Class<?>... parameterTypes):表示调用指定的一个本类中的方法(不包括继承的)
参数:
methodName: 表示被调用方法的名字
parameterTypes:表示被调用方法的参数的Class类型如String.class
[code]public class User { public User() { System.out.println("---"); } public User(String name) { System.out.println(name); } public User(String name, String school) { System.out.println(name + " " + school); } public void Say(String name) { System.out.println(name); } public void Say(String name, String school) { System.out.println(name + " " + school); } }
[code]Class clz=User.class; Method[] m=clz.getMethods(); for (Method c : m) { System.out.println(c); } System.out.println("----------------------"); m=clz.getDeclaredMethods(); for (Method c : m) { System.out.println(c); }
[code]Method m1=clz.getMethod("Say", String.class); System.out.println(m1); Method m2=clz.getMethod("Say", String.class,String.class); System.out.println(m2);
- 点赞
- 收藏
- 分享
- 文章举报
- java学习(6) java反射以及应用
- Java反射的高级应用,模拟开发环境IDE动态搜索类成员以及方法,。。。。。
- java 高新技术【9.2】 泛型类以及反射在泛型中的应用
- 对java反射的理解,以及应用(实现简易ORM)。
- Java反射在Android中的应用,以及注意事项
- 类加载和Java反射以及动态代理的简介及应用~
- Java反射高级应用--利用反射调用类的私有方法修改私有方法值,以及替换Java的类成员数据
- Java反射高级应用--利用反射调用类的私有方法修改私有方法值,以及替换Java的类成员数据
- Java反射的高级应用,模拟开发环境IDE动态搜索类成员以及方法,。。。。。
- Java反射的高级应用,模拟开发环境IDE动态搜索类成员以及方法,。。。。。
- java 高新技术【9.2】 泛型类以及反射在泛型中的应用
- Java反射高级应用--利用反射调用类的私有方法修改私有方法值,以及替换Java的类成员数据
- JAVA中代理与反射的应用(附源码)
- JavaWeb开发中Setvlet的部署以及应用
- 什么是正则表达式以及在Java1.4中的应用
- Java 编程的动态性,第3部分: 应用反射
- JSP开发中的JavaBean的应用以及部署
- .Net反射技术应用—与Java互操作
- C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)
- Java中的反射学习及反射解耦应用