1, Class.forName("全类名");//多用于读取文件,加载类 2, 类名.cLass;//多用于传参 3, 对象.getClass();//多用于对象获取字节码文件(class)
附上代码帮助理解:
package Reflect; import domain.person; public class ReflectClass { public static void main(String[] args) throws Exception { //1,Class.forName("全类名"); Class cls1 = Class.forName("domain.person"); System.out.println(cls1); //2,类名.cLass; Class cls2=person.class; System.out.println(cls2); //3,对象.getClass(); person p=new person(); Class cls3 = p.getClass(); System.out.println(cls3); } }
运行结果为
class domain.person class domain.person class domain.person
思考:这三个对象是同一个吗????(地址是否相同)
验证这个问题我们可以使用 == 来判断,
这时有人会问,两个对象相比较不应该是equals()吗?
这里要注意equals()比较的是两个对象的内容而 == 比较的是两个对象在物理内存的地址
修改一些代码,如下
public static void main(String[] args) throws Exception { //1,Class.forName("全类名"); Class cls1 = Class.forName("domain.person"); System.out.println(cls1); //2,类名.cLass; Class cls2=person.class; System.out.println(cls2); //3,对象.getClass(); person p=new person(); Class cls3 = p.getClass(); System.out.println(cls3); System.out.println(cls1==cls2); System.out.println(cls1==cls3); System.out.println(cls2==cls3); }
运行结果
class domain.person class domain.person class domain.person true true true
由此可见 三种方法取到的地址都为同一个,所以三个对象是同一个
结论:程序运行一次 .class文件只会被加载一次 不论通过哪种方式获取Class对象 他们都是同一个
那么创建Class对象有什么用呢
1. 获取成员变量 Field[] getFields() :获取所有public修饰的成员变量 Field getField(String name) 获取指定名称的 public修饰的成员变量 Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符 Field getDeclaredField(String name) 2. 获取构造方法 Constructor<?>[] getConstructors() Constructor<T> getConstructor(类<?>... parameterTypes) Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) Constructor<?>[] getDeclaredConstructors() 3. 获取成员方法 Method[] getMethods() Method getMethod(String name, 类<?>... parameterTypes) Method[] getDeclaredMethods() Method getDeclaredMethod(String name, 类<?>... parameterTypes) 4. 获取全类名 String getName()
这时我们就可以测试一下这些方法
1.首先看看获取成员变量的各种方法
先贴出 person里的代码:
package domain; public class person { private String name; private int age; public String a; public String a2; protected String b; String c;//default private String d; public person(String name, int age) { this.name = name; this.age = age; } public person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", a2='" + a2 + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; } public void upp() { System.out.println("hello"); } public void upp(String s) { System.out.println("hello"+s); } }
对变量进行操作
package Reflect; import domain.person; import java.lang.reflect.Field; public class ReflectClass_value_demo { public static void main(String[] args) throws Exception { Class cls2= person.class; person p=new person(); //获取所有public Field[] field=cls2.getFields(); for (Field get:field) { System.out.println(get); } System.out.println("=====================对public成员变量进行操作==================="); //获取成员变量a Field a=cls2.getField("a"); System.out.println(a); a.set(p,"zhangsan");//设置p对象的成员变量a的value Object value =a.get(p);//获取p对象中的a的值 System.out.println(value); System.out.println("====================获取全部成员变量(包括私有的)===================="); //获取全部成员变量 Field[] field2=cls2.getDeclaredFields(); for (Field get:field2) { System.out.println(get); } System.out.println("=====================获取单个私有成员变量 通过暴力反射获取,设置值==================="); //获取单个成员变量 Field defield=cls2.getDeclaredField("d");//d为private defield.setAccessible(true);//暴力反射 可以忽略访问修饰符 Object value2=defield.get(p); System.out.println("set before = "+value2); defield.set(p,"hello"); value2=defield.get(p); System.out.println("set after = "+value2); } }
输出结果为
public java.lang.String domain.person.a public java.lang.String domain.person.a2 =====================对public成员变量进行操作=================== public java.lang.String domain.person.a zhangsan ====================获取全部成员变量(包括私有的)==================== private java.lang.String domain.person.name private int domain.person.age public java.lang.String domain.person.a public java.lang.String domain.person.a2 protected java.lang.String domain.person.b java.lang.String domain.person.c private java.lang.String domain.person.d =====================获取单个私有成员变量 通过暴力反射获取,设置值=================== set before = null set after = hello
2.对构造方法进行操作:
package Reflect; import java.lang.reflect.Constructor; public class ReflectClass_fangfa_demo { public static void main(String[] args) throws Exception { Class p_class=Class.forName("domain.person"); System.out.println("=======================获取构造方法,创建构造器=============================="); Constructor constructor=p_class.getConstructor();//获取无参 System.out.println(constructor); Constructor constructor1=p_class.getConstructor(String.class,int.class);//获取有参 System.out.println(constructor1); System.out.println("=========================使用构造器创建对象================================="); Object a=constructor.newInstance(); System.out.println(a); Object b=constructor1.newInstance("王二狗",18); System.out.println(b); } }
运行结果:
=======================获取构造方法,创建构造器============================== public domain.person() public domain.person(java.lang.String,int) =========================使用构造器创建对象================================= person{name='null', age=0, a='null', a2='null', b='null', c='null', d='null'} person{name='王二狗', age=18, a='null', a2='null', b='null', c='null', d='null'}
3.对方法进行操作
package Reflect; import domain.person; import java.lang.reflect.Method; public class ReflectClass_Method_demo { public static void main(String[] args) throws Exception { Class p_class= person.class; System.out.println("=============获取指定名称的无参方法============="); Method upp = p_class.getMethod("upp"); person p=new person(); upp.invoke(p); System.out.println("=============获取指定名称的有参方法============="); Method upp1 = p_class.getMethod("upp", String.class); upp1.invoke(p," word"); System.out.println("==============获取所有public方法========================"); Method[] upp2 = p_class.getMethods(); for (Method k:upp2) { System.out.println(k.getName());//获取方法名 } } }
输出结果
=============获取指定名称的无参方法============= hello =============获取指定名称的有参方法============= hello word ==============获取所有public方法======================== getName toString setName upp upp getAge setAge wait wait wait equals hashCode getClass notify notifyAll