认识Java反射机制
在正常情况下,必须知道一个类才可以实例化对象,但是在Java中也通过一个对象来找到其所在的类的信息,那么这实际上是Class类的功能。
Java代码 package zyz.demo; class X{ }; public class GetClassDemo01{ public static void main(String args[]){ X x = new X() ; // 实例化X类的对象 System.out.println(x.getClass().getName()) ; // 得到对象所在的类的完整名字 } }; 结果:zyz.demo.X
实例化Class类型对象
实例化Class类型对象的方法有三种:
第一种:通过forName()方法
第二种:类.class
第三种:对象.getClass()
Java代码 package zyz.demo; class X{ }; public class GetClassDemo02{ public static void main(String args[]){ Class<?> c1 = null ; // 指定泛型 Class<?> c2 = null ; // 指定泛型 Class<?> c3 = null ; // 指定泛型 try{ // 以下的操作形式是在开发中最常用的一种形式 c1 = Class.forName("org.lxh.demo15.getclassdemo.X") ; }catch(ClassNotFoundException e){ e.printStackTrace() ; } c2 = new X().getClass() ; // 通过Object类中的方法实例化 c3 = X.class ; // 通过类.class实例化 System.out.println("类名称:" + c1.getName());// 得到类的名称 System.out.println("类名称:" + c2.getName());// 得到类的名称 System.out.println("类名称:" + c3.getName());// 得到类的名称 } };
一旦可以实例化Class类之后,就可以进行反射的进一步操作。
1、实例化对象
Java代码 <strong>class Person{ private String name ; // name属性 private int age ; // age属性 public void setName(String name){ this.name = name ; } public void setAge(int age){ this.age = age ; } public String getName(){ return this.name ; } public int getAge(){ return this.age ; } public String toString(){ // 覆写toString()方法 return "姓名:" + this.name + ",年龄:" + this.age ; } }; public class Demo01{ public static void main(String args[]){ Class<?> c = null ; // 声明Class对象 try{ c = Class.forName("org.lxh.demo15.instancedemo.Person") ; }catch(ClassNotFoundException e){ e.printStackTrace() ; } Person per = null ; // 声明Person对象 try{ per = (Person)c.newInstance() ; // 实例化对象 }catch(Exception e){ e.printStackTrace() ; } per.setName("李兴华") ; // 设置姓名 per.setAge(30) ; // 设置年龄 System.out.println(per) ; // 内容输出,调用toString() } }; </strong>
通过以上的代码,可以发现,即使不使用关键字new对象也可以进行实例化操作,反射的作用。但是,在使用以上操作的时候有一点必须注意,在操作中类中必须存在无参构造方法。否则无法实例化。
所以说,使用以上的方法实际上还是需要类中构造方法的支持,符合于对象的实例化需求。
如果要想调用有参,由必须按照以下的步骤进行:
1、通过Class类中的getConstructors()取得本类中的全部构造方法。
2、向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数。
3、之后通过Constructor实例化对象
Java代码 package org.lxh.demo15.instancedemo ; import java.lang.reflect.Constructor ; // 导入反射机制包 class Person{ private String name ; // name属性 private int age ; // age属性 public Person(String name,int age){ this.setName(name) ; this.setAge(age); } public void setName(String name){ this.name = name ; } public void setAge(int age){ this.age = age ; } public String getName(){ return this.name ; } public int getAge(){ return this.age ; } public String toString(){ // 覆写toString()方法 return "姓名:" + this.name + ",年龄:" + this.age ; } }; public class InstanceDemo03{ public static void main(String args[]){ Class<?> c = null ; // 声明Class对象 try{ c = Class.forName("org.lxh.demo15.instancedemo.Person") ; }catch(ClassNotFoundException e){ e.printStackTrace() ; } Person per = null ; // 声明Person对象 Constructor<?> cons[] = null ; cons = c.getConstructors() ; try{ // 第一个数组 per = (Person)cons[0].newInstance("李兴华",30) ; // 实例化对象 }catch(Exception e){ e.printStackTrace() ; } System.out.println(per) ; // 内容输出,调用toString() } };
但是,从实际角度看,如果要使用反射进行对象的实例化操作,最好在类中存在无参构造。
2、取得类所实现的全部接口
Java代码 package org.lxh.demo15.classinfodemo ; public class GetInterfaceDemo{ public static void main(String args[]){ Class<?> c1 = null ; // 声明Class对象 try{ c1 = Class.forName("org.lxh.demo15.Person") ; // 实例化对象 }catch(ClassNotFoundException e){ e.printStackTrace() ; } Class<?> c[] = c1.getInterfaces() ; // 以数组形式返回实现的全部接口 for(int i=0;i<c.length;i++){ System.out.println("实现的接口名称:" + c[i].getName()) ; // 输出接口名称 } } }; 结果:实现的接口名称:org.lxh.demo15.China
3、取得父类
Java代码 <strong>package org.lxh.demo15.classinfodemo ; public class GetSuperClassDemo{ public static void main(String args[]){ Class<?> c1 = null ; // 声明Class对象 try{ c1 = Class.forName("org.lxh.demo15.Person") ; // 实例化对象 }catch(ClassNotFoundException e){ e.printStackTrace() ; } Class<?> c2 = c1.getSuperclass() ; // 取得父类 System.out.println("父类名称:" + c2.getName()) ; } }; 结果:父类名称:java.lang.Object </strong>
4、取得类中的全部构造方法
Java代码 package org.lxh.demo15.classinfodemo ; import java.lang.reflect.Constructor ; // 导入构造方法的包 public class GetConstructorDemo01{ public static void main(String args[]){ Class<?> c1 = null ; // 声明Class对象 try{ c1 = Class.forName("org.lxh.demo15.Person") ; // 实例化对象 }catch(ClassNotFoundException e){ e.printStackTrace() ; } Constructor<?> con[] = c1.getConstructors() ; // 取得一个类中的全部构造 for(int i=0;i<con.length;i++){ System.out.println("构造方法:" + con[i]) ; // 输出构造,直接打印 } } }; 结果: 构造方法:public org.lxh.demo15.Person() 构造方法:public org.lxh.demo15.Person(java.lang.String) 构造方法:public org.lxh.demo15.Person(java.lang.String,int)
以上的操作确实取得了类中的构造方法,但是此时是通过对象直接打印取得的,肯定会调用Constructor类中的toString()方法。
Constructor类中存在了以下的几个方法:
取得修饰符:public int getModifiers()
取得方法名称:public String getName()
取得参数的类型:public Class<?>[] getParameterTypes()
Java代码 package org.lxh.demo15.classinfodemo ; import java.lang.reflect.Constructor ; // 导入构造方法的包 public class GetConstructorDemo02{ public static void main(String args[]){ Class<?> c1 = null ; // 声明Class对象 try{ c1 = Class.forName("org.lxh.demo15.Person") ; // 实例化对象 }catch(ClassNotFoundException e){ e.printStackTrace() ; } Constructor<?> con[] = c1.getConstructors() ; // 取得一个类中的全部构造 for(int i=0;i<con.length;i++){ Class<?> p[] = con[i].getParameterTypes() ; // 得到构造方法中的全部参数 System.out.print("构造方法:" ) ; // 输出构造,直接打印 System.out.print(con[i].getModifiers() + " ") ; // 得到修饰符 System.out.print(con[i].getName()) ; // 取得构造方法的名字 System.out.print("(") ; for(int j=0;j<p.length;j++){ System.out.print(p[j].getName() + " arg" + i) ; if(j<p.length-1){ // 判断此是否是最后一个参数 System.out.print(","); // 输出“,” } } System.out.println("){}") ; } } };