Java中Class类的使用,反射机制
反射:把Java中的各种数据(方法、属性、构造器、类名)映射成一个个Java对象。
可以通过Class类创建一个类,获取类的信息,操作类的属性。
准备一个Uer类,在 package lurenjia.leaning; 包下,有int id、int age、String name三个私有属性,及其对应的set/get方法(其中 setId 为 private 私有方法),一个无参构造器和一个有参构造器。
package lurenjia.leaning; public class User { private int id; private int age; private String name; public int getId() { return id; } private void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public User() { } public User(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } }
一、获取Class对象
方式一:有此类的对象,直接通过getClass()方法获取。
public static void main(String[] args) { User t= new User(); Class cl =t.getClass(); }
方式二:能够直接使用类的时候,通过类名.class获取。
public static void main(String[] args) { Class cls = User.class; }
方式三:通过静态方法Class.forName("包名.类名")。
public static void main(String[] args) throws ClassNotFoundException { Class cls = Class.forName("lurenjia.leaning.User"); }
方式四:通过子类的类对象获取
//获取子类的类对象 Class son = Son.class; //获取自身的类对象 Class father = son.getSuperclass();
二、通过Class对象获取类信息
1、获取类的实例(Instance)
public static void main(String[] args) throws Exception{ Class cls = Class.forName("java.lang.String"); //jdk9以前,使用Class对象创建一个String对象 String str0 = (String)cls.newInstance(); //jdk9推荐方式:使用构造器创建对象,所以它推荐所有类加入无参构造器。 String str1 = (String) cls.getConstructor().newInstance("iloveyou");
}
2、获取类名(Name)
getName 包括包名
getSimpleName 不包括包名
public static void main(String[] args) throws Exception{ Class clszz = Class.forName("lurenjia.leaning.User"); //获取类名,包括包名 System.out.println(clszz.getName()); //获取类名,不包括包名 System.out.println(clszz.getSimpleName()); }
运行结果:
3、 获取属性(Filed)、方法(Method)、构造器(Constructor):
public static void main(String[] args) throws Exception{ Class clszz = Class.forName("lurenjia.leaning.User"); //获取指定public属性,不存在会抛出异常 //Field field=clszz.getField("id"); //获取指定属性 Field field2=clszz.getDeclaredField("id"); //获取所有的public属性,包括它的父类的public属性 Field[] fields=clszz.getFields(); //获取所有的属性 Field[] fields2=clszz.getDeclaredFields(); //获取指定public方法 Method method = clszz.getMethod("setId", int.class); //获取指定方法,带参数则输入参数类型.class,无参则null Method method2 = clszz.getDeclaredMethod("setId", int.class); //获取所有的public方法 Method[] methods = clszz.getMethods(); //获取所有的方法 Method[] methods2 = clszz.getDeclaredMethods(); //获取public无参构造器 Constructor constructor = clszz.getConstructor(); //获取指定public带参数的构造器 Constructor constructor2 = clszz.getConstructor(int.class,int.class,String.class); //获取所有public构造器 Constructor[] constructors = clszz.getConstructors(); //获取所有的构造器 Constructor[] constructors2 = clszz.getDeclaredConstructors(); }
总结:
Class对象获取信息:
获取public:使用:get 属性(Filed)、方法(Method)、构造器(Constructor)。
获取非public:使用:getDeclared 属性(Filed)、方法(Method)、构造器(Constructor)。
获取全部:+s,返回数组。获取public会获取到父类的,Declared则会获取自身的。
三、通过Class对象操作实际对象
1、使用对象的方法:
public static void main(String[] args) throws Exception{ //创建一个User对象 User u1 = new User(1,18,"二狗子"); //获取User类的Class对象 Class c = u1.getClass(); //获取User类的setId方法 Method method = c.getDeclaredMethod("setName", String.class); //操作u1中的setName方法 method.invoke(u1,"老苗子"); }
2、操作对象的属性:
public static void main(String[] args) throws Exception{ //创建一个User对象 User u1 = new User(1,18,"二狗子"); //获取User类的Class对象 Class c = u1.getClass(); //获取User类的name属性 Field field = c.getDeclaredField("name"); //将此反射对象的accessible标志设置为指示的布尔值,值为true表示反射对象应该在使用Java语言访问控制时抑制检查。 field.setAccessible(true); //操作u1的属性 field.set(u1,"老苗子"); //获取u1的属性 System.out.println(field.get(u1)); }
注意:如果属性为私有属性,我们可以通过设置accessible标识来抑制检查,达到访问效果:
setAccessible(true); (设置是否禁用 访问的安全检查。)它可以提供反射运行的速度。