在正常情况下,需要先有一个类的完整路径引入之后才可以按照固定的格式产生实例话对象,但是在Java中也允许通过一个实例话对象找到一个类的完整信息。那么这就是Class类的功能。
实际上类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即可以通过对象的反射求出类的名称。
实例化Class类,获得字节码文件的方法有三种:
第一种:通过forName()方法;第二种:类。class第三种:对象。getClass()
package toto.learn;
class X1{}
publicclass GetClassDemo02 {
publicstaticvoid main(String[] args) {
Class c1=null;//指定泛型
Class c2=null;//指定泛型
Class c3=null;//指定泛型
try{
c1=Class.forName("toto.learn.X");//最常用的形式,这种方式将字节码文件加载到内存中。
}catch(ClassNotFoundException e){
e.printStackTrace();
}
c2 = new X1()。getClass();//通过Object类中的方法实例
c3 = X1.class;//通过类class实例化
System.out.println("类名称:"+c1.getName());//得到类的名称
System.out.println("类名称:"+c2.getName());//得到类的名称
System.out.println("类名称:"+c3.getName());//得到类的名称
}
}
通过以上方法获得类名称的方式得到的是包名+类名
如果要想通过Class类本身实例化其他类的对象,则可以使用newInstance()方法,但是必须要保证被实例化的类中必须存在一个无参够造方法。
被实例化对象的类中必须存在无参构造方法,如果不存在的话,则肯定是无法实例化的。
1、 通过Class类中的getConstructors()取得本类中的全部构造方法
2、 向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数
3、 之后通过Constructor实例化对象。
package org.lxh.demo15.instancedemo;
import java.lang.reflect.Constructor;
publicclass InstanceDemo03 {
publicstaticvoid main(String[] args) {
Class c = null;
try {
c = Class.forName("org.lxh.demo15.instancedemo.Person"); // 声明Class对象
} 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) { // 因为只有一个构造,所以数组下标为0
e.printStackTrace();
}
System.out.println(per); // 输出对象
}
}
per = (Person)cons[0].newInstance("李兴华", 30); //此处是调用并使用构造方法的部分。
在声明对象数组的时候,必须考虑到构造方法中参数的类型顺序,所以第一个参数的类型为Stirng,第二个参数的类型WieInteger(在使用是可以自动拆箱)
Constructorcons[]=null;//实例化构造方法的数组
Cons =c.getConstructors();//取得全部构造
//向构造方法中传递参数,此方使用可变参数接收,并实例化对象
Per = (Person)cons[0].newInstance("李兴华",30);
设置构造方法的参数内容
publicPerson(String name,int age){//通过构造设置属性内容
}
反射的应用
可以使用反射取得实现的全部接口
可以使用反射取得一个类所继承的父类
可以使用反射取得一个类中的全部构造方法
可以使用反射取得一个类中的全部方法
可以使用反射取得一个类中的全部属性
在实际开发中发,以上的程序就是反射应用最多的地方,当然反射机制所提供的功能远不如此,还可以通过反射得到一个类中的完整构造,那么这就要使用到java.lang.reflect包中的一下几个类。
Constructor:表示类中的构造方法
Field:表示类中的属性
Method:表示类中的方法
这三个类都是AccessibleObject类中的子类。
要想取得一个类中所实现的全部接口,则必须使用Class类中的getInterfaces()方法。此方法定义如下:
publicClass[] getInterfaces();
此方法返回一个Class类的对象数组,之后就可以直接利用Class类中的getName()方法输出即可。
通过反射取得实现的全部接口
package org.lxh.demo15;
publicclass GetInterfaceDemo {
publicstaticvoid main(String[] args) {
Class c1 =null;//声明Class对象
try{
c1 = Class.forName("org.lxh.demo15.Person");//实例化Class对象
}catch(ClassNotFoundException e){
e.printStackTrace();
}
Class c[] = c1.getInterfaces();//取得实现的全部接口
for(int i=0;i
System.out.println("实现的接口名称:"+c[i].getName());//输出接口名称
}
}
}
一个类中可以实现多个接口,但是只能继承一个父类,所以如果要想取得一个类的父类,可以直接使用Class类中的getSuperclass()方法。此方法定义如下:
PublicClass getSuperclass()
此方法返回的是Class实例,和之前的得到接口一样,可以通过getName()方法取得名称。
取得构造方法的例子:
package org.lxh.demo15;
import java.lang.reflect.Constructor;//导入反射操作包
publicclass GetConstructorDemo01 {
publicstaticvoid 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
System.out.println("构造方法:"+con[i]);//直接打印输出
}
}
}
还原修饰符
在整个Java中对于方法的修饰符使用一定的数字表示出来的,而如果要想把这个数字还原成用户可以看懂的关键字,则必须依靠Modifier类完成,此类定义在java.lang.reflect包中。直接使用Modifer类的一下方法可修饰符:
publicstatic String toString(int mod)
int mo = con[i].getModifiers();
System.out.print(Modifier.toString(mo)+""); //还原权限
getDeclaredMethods()方法,此方法返回一个Method类的对象数组,而如果要想进一步取得方法具体信息,例如:方法的参数,抛出的异常声明等等,则就是必须依靠Method类
再反射操作中同样可以取得一个类中的全部属性,但是在取得属性的时候有以下两种不同的操作:
得到实现的接口或父类中的公共属性:public Field[] getFields() throwsSecurityException
得到本类中自己定义的的全部属性:public Field[] getDeclaredFields() throws SecurityException
如果要使用反射调用类中的方法可以通过Method类完成,操作步骤如下:
1、 通过Class类的getMethod(Stringname,Class…parameterTypes)方法取得一个Method的对象,并设置此方法操作时所需的参数类型。
2、 之后才可以使用invoke进行调用,并向方法中传递要设置的参数
posted on 2014-03-18 17:21 好不容易 阅读(143) 评论(0) 编辑 收藏