Java 反射机制
---------------
认识Class类
在正常情况下,必须知道一个类的完整路径之后才可以实例化对象,但是在JAVA中也允许通过一个对象来找到其所在的类的信息,那么这实际上就是 Class类的功能。
package org.cwt.demo15.getclassdemo ;
class X{
};
public class GetClassDemo01{
publicstatic void main(String args[]){
Xx = new X() ; // 实例化X类的对象
System.out.println(x.getClass().getName()); // 得到对象所在的类
}
};
此时,所有的操作都是反着来的。
Object类的支持
在Object类中定义了以下的方法,此方法将被所有子类继承:
publicfinal Class getClass()
以上的方法返回值的类型是一个“Class”类,实际上此类是JAVA反射的源头。可以通过对象反射求出类的名称。
Class类
Class本身表示一个类的本身,通过Class可以完整的得到一个类中的完整结构,包括此类中的方法定义,属性定义等。
实例化Class类对象
第一种:通过forName()方法
第二种:类.Class
第三种:对象.getClass()
实例:
package org.cwt.demo15.getclassdemo ;
class X{
};
public class GetClassDemo02{
publicstatic void main(String args[]){
Class<?>c1 = null ; // 指定泛型
Class<?>c2 = null ; // 指定泛型
Class<?>c3 = null ; // 指定泛型
try{
//以下的操作形式是在开发中最常用的一种形式
c1= Class.forName("org.cwt.demo15.getclassdemo.X") ;
}catch(ClassNotFoundExceptione){
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类的使用
Class主要是反射的源头,不光可以取得对象所在的类的信息,也可以直接通过Class类的方法进行对象的实例化操作。
实例:
package org.cwt.demo15.instancedemo ;
class Person{
privateString name ; // name属性
privateint age ; // age属性
publicvoid setName(String name){
this.name= name ;
}
publicvoid setAge(int age){
this.age= age ;
}
publicString getName(){
returnthis.name ;
}
publicint getAge(){
returnthis.age ;
}
publicString toString(){ // 覆写toString()方法
return"姓名:" +this.name + ",年龄:" + this.age ;
}
};
public class InstanceDemo01{
publicstatic void main(String args[]){
Class<?>c = null ; // 声明Class对象
try{
c= Class.forName("org.cwt.demo15.instancedemo.Person") ;
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
Personper = null ; // 声明Person对象
try{
per= (Person)c.newInstance() ; // 实例化对象
}catch(Exceptione){
e.printStackTrace();
}
per.setName("曹文涛") ; // 设置姓名
per.setAge(26); // 设置年龄
System.out.println(per); // 内容输出,调用toString()
}
};
通过以上的代码,可以发现,即使不使用关键字new对象也可以进行实例化操作。
但是在使用以上操作的时候,在操作类中必须存在无参构造方法,否则无法实例化。
实例:
package org.cwt.demo15.instancedemo ;
class Person{
privateString name ; // name属性
privateint age ; // age属性
publicPerson(String name,int age){
this.setName(name);
this.setAge(age);
}
publicvoid setName(String name){
this.name= name ;
}
publicvoid setAge(int age){
this.age= age ;
}
publicString getName(){
returnthis.name ;
}
publicint getAge(){
returnthis.age ;
}
publicString toString(){ // 覆写toString()方法
return"姓名:" +this.name + ",年龄:" + this.age ;
}
};
public class InstanceDemo02{
publicstatic void main(String args[]){
Class<?>c = null ; // 声明Class对象
try{
c= Class.forName("org.cwt.demo15.instancedemo.Person") ;
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
Personper = null ; // 声明Person对象
try{
per= (Person)c.newInstance() ; // 实例化对象
}catch(Exceptione){
e.printStackTrace();
}
per.setName("曹文涛") ; // 设置姓名
per.setAge(26); // 设置年龄
System.out.println(per); // 内容输出,调用toString()
}
};
以上程序会出现错误。
所以发现,使用以上的方式实际上还是需要类中的构造方法的支持。
实例:调用有参构造方法完成实例化
package org.cwt.demo15.instancedemo ;
import java.lang.reflect.Constructor ; // 导入反射机制包
class Person{
privateString name ; // name属性
privateint age ; // age属性
publicPerson(String name,int age){
this.setName(name);
this.setAge(age);
}
publicvoid setName(String name){
this.name= name ;
}
publicvoid setAge(int age){
this.age= age ;
}
publicString getName(){
returnthis.name ;
}
publicint getAge(){
returnthis.age ;
}
publicString toString(){ // 覆写toString()方法
return"姓名:" +this.name + ",年龄:" + this.age ;
}
};
public class InstanceDemo03{
publicstatic void main(String args[]){
Class<?>c = null ; // 声明Class对象
try{
c= Class.forName("org.cwt.demo15.instancedemo.Person") ;
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
Personper = null ; // 声明Person对象
Constructor<?>cons[] = null ;
cons= c.getConstructors() ;
try{
per= (Person)cons[0].newInstance("曹文涛",26) ; // 实例化对象
}catch(Exceptione){
e.printStackTrace();
}
System.out.println(per); // 内容输出,调用toString()
}
};
反射应用——取得类的结构
定义操作类Person:
package org.cwt.demo15 ;
interface China{ // 定义China接口
publicstatic final String NATIONAL = "China" ; // 定义全局常量
publicstatic final String AUTHOR = "曹文涛" ; // 定义全局常量
publicvoid sayChina() ; // 无参的,没有返回值的方法
publicString sayHello(String name,int age) ; //定义有两个参数的方法,并返回内容
}
public class Person implements China{
privateString name ;
privateint age ;
publicPerson(){ // 无参构造
}
publicPerson(String name){
this.name= name ; // 设置name属性
}
publicPerson(String name,int age){
this(name);
this.age= age ;
}
publicvoid sayChina(){ // 覆写方法
System.out.println("作者:" + AUTHOR + ",国籍:" + NATIONAL) ;
}
publicString sayHello(String name,int age){
returnname + ",你好!我今年:"+ age + "岁了!" ;
}
publicvoid setName(String name){
this.name= name ;
}
publicvoid setAge(int age){
this.age= age ;
}
publicString getName(){
returnthis.name ;
}
publicint getAge(){
returnthis.age ;
}
};
实例:取得类所实现的全部接口
package org.cwt.demo15.classinfodemo ;
public class GetInterfaceDemo{
publicstatic void main(String args[]){
Class<?>c1 = null ; // 声明Class对象
try{
c1= Class.forName("org.cwt.demo15.Person") ; // 实例化对象
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
Class<?>c[] = c1.getInterfaces() ; // 以数组形式返回实现的全部接口
for(inti=0;i<c.length;i++){
System.out.println("实现的接口名称:" + c[i].getName()) ; // 输出接口名称
}
}
};
实例:取得类所继承的父类
package org.cwt.demo15.classinfodemo ;
public class GetSuperClassDemo{
publicstatic void main(String args[]){
Class<?>c1 = null ; // 声明Class对象
try{
c1= Class.forName("org.cwt.demo15.Person") ; // 实例化对象
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
Class<?>c2 = c1.getSuperclass() ; // 取得父类
System.out.println("父类名称:" + c2.getName()) ;
}
};
实例:取得类中的全部构造方法
package org.cwt.demo15.classinfodemo ;
import java.lang.reflect.Constructor ; // 导入构造方法的包
import java.lang.reflect.Modifier ; // 导入构造方法的包
public class GetConstructorDemo03{
publicstatic void main(String args[]){
Class<?>c1 = null ; // 声明Class对象
try{
c1= Class.forName("org.cwt.demo15.Person") ; // 实例化对象
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
Constructor<?>con[] = c1.getConstructors() ; // 取得一个类中的全部构造
for(inti=0;i<con.length;i++){
Class<?>p[] = con[i].getParameterTypes() ; //得到构造方法中的全部参数
System.out.print("构造方法:" ) ; // 输出构造,直接打印
intmo = con[i].getModifiers() ; // 得到所要的访问权限
System.out.print(Modifier.toString(mo)+ " ") ; // 得到修饰符
System.out.print(con[i].getName()); // 取得构造方法的名字
System.out.print("(");
for(intj=0;j<p.length;j++){
System.out.print(p[j].getName()+ " arg" + i) ;
if(j<p.length-1){
//判断此是否是最后一个参数
System.out.print(","); // 输出“,”
}
}
System.out.println("){}");
}
}
};
实例:取得类中的方法
package org.cwt.demo15.classinfodemo ;
import java.lang.reflect.Method ; // 导入构造方法的包
import java.lang.reflect.Modifier ; // 导入构造方法的包
public class GetMethodDemo{
publicstatic void main(String args[]){
Class<?>c1 = null ; // 声明Class对象
try{
c1= Class.forName("org.cwt.demo15.Person") ; // 实例化对象
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
Methodm[] = c1.getMethods() ; // 取得全部方法
for(inti=0;i<m.length;i++){
Class<?>r = m[i].getReturnType() ; // 得到返回值类型
Class<?>p[] = m[i].getParameterTypes() ; // 取得全部参数的类型
intxx = m[i].getModifiers() ; // 得到修饰符
System.out.print(Modifier.toString(xx)+ " ") ; // 输出修饰符
System.out.print(r+ " ") ;
System.out.print(m[i].getName());
System.out.print("(");
for(intj=0;j<p.length;j++){
System.out.print(p[j].getName()+ " " + "arg" + j) ;
if(j<p.length-1){
System.out.print(",");
}
}
Class<?>ex[] = m[i].getExceptionTypes() ; // 取出异常
if(ex.length>0){
System.out.print(")throws ") ;
}else{
System.out.print(")");
}
for(intj=0;j<ex.length;j++){
System.out.print(ex[j].getName());
if(j<p.length-1){
System.out.print(",");
}
}
System.out.println();
}
}
};
实例:取得类中的属性
package org.cwt.demo15.classinfodemo ;
import java.lang.reflect.Field ; // 导入构造方法的包
import java.lang.reflect.Modifier ; // 导入构造方法的包
public class GetFieldDemo{
publicstatic void main(String args[]){
Class<?>c1 = null ; // 声明Class对象
try{
c1= Class.forName("org.cwt.demo15.Person") ; // 实例化对象
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
{ // 本类属性
Fieldf[] = c1.getDeclaredFields() ; // 取得本类中的属性
for(inti=0;i<f.length;i++){
Class<?>r = f[i].getType() ; // 得到属性类型
intmo = f[i].getModifiers() ; // 得到修饰符的数字
Stringpriv = Modifier.toString(mo) ; // 还原修饰符
System.out.print("本类属性:") ;
System.out.print(priv+ " ") ;
System.out.print(r.getName()+ " ") ; // 得到属性类型
System.out.print(f[i].getName()); // 输出属性名称
System.out.println(";") ;
}
}
{ // 公共属性
Fieldf[] = c1.getFields() ; // 取得本类中的公共属性
for(inti=0;i<f.length;i++){
Class<?>r = f[i].getType() ; // 得到属性类型
intmo = f[i].getModifiers() ; // 得到修饰符的数字
Stringpriv = Modifier.toString(mo) ; // 还原修饰符
System.out.print("公共属性:") ;
System.out.print(priv+ " ") ;
System.out.print(r.getName()+ " ") ; // 得到属性类型
System.out.print(f[i].getName()); // 输出属性名称
System.out.println(";") ;
}
}
}
};
Java反射机制的深入研究
通过反射调用类中的方法:在正常情况下一个类的反射功能产生之后,就可以直接调用类中的方法了,如果要想调用的话,则必须知道方法名称是什么,之后通过Class类中的方法调用。
定义操作类:
package org.cwt.demo15 ;
interface China{ // 定义China接口
publicstatic final String NATIONAL = "China" ; // 定义全局常量
publicstatic final String AUTHOR = "曹文涛" ; // 定义全局常量
publicvoid sayChina() ; // 无参的,没有返回值的方法
publicString sayHello(String name,int age) ; //定义有两个参数的方法,并返回内容
}
public class Person implements China{
privateString name ;
privateint age ;
publicPerson(){ // 无参构造
}
publicPerson(String name){
this.name= name ; // 设置name属性
}
publicPerson(String name,int age){
this(name);
this.age= age ;
}
publicvoid sayChina(){ // 覆写方法
System.out.println("作者:" + AUTHOR + ",国籍:" + NATIONAL) ;
}
publicString sayHello(String name,int age){
returnname + ",你好!我今年:"+ age + "岁了!" ;
}
publicvoid setName(String name){
this.name= name ;
}
publicvoid setAge(int age){
this.age= age ;
}
publicString getName(){
returnthis.name ;
}
publicint getAge(){
returnthis.age ;
}
};
实例操作:
package org.cwt.demo15.invokedemo ;
import java.lang.reflect.Method ;
public class InvokeSayHelloDemo{
publicstatic void main(String args[]){
Class<?>c1 = null ;
try{
c1= Class.forName("org.cwt.demo15.Person") ; // 实例化Class对象
}catch(Exceptione){}
try{
Method met =c1.getMethod("sayHello",String.class,int.class) ; // 找到sayChina()方法
Stringrv = null ;
rv= (String)met.invoke(c1.newInstance(),"曹文涛",26) ; // 调用方法
System.out.println(rv);
}catch(Exceptione){
e.printStackTrace();
}
}
};
通过反射调用setter及getter
setter及getter方法是一个标准的属性的访问方法,如果一个类的属性被封装,则必须通过setter及getter方法设置和取得,实际上此方法的操作之所以这样规定,主要原因就是由于反射机制可以给予支持。
实例:通过反射调用setter及getter方法
package org.cwt.demo15.invokedemo ;
import java.lang.reflect.Method ;
public class InvokeSetGetDemo{
publicstatic void main(String args[]){
Class<?>c1 = null ;
Objectobj = null ;
try{
c1= Class.forName("org.cwt.demo15.Person") ; // 实例化Class对象
}catch(Exceptione){}
try{
obj= c1.newInstance() ;
}catch(Exceptione){}
setter(obj,"name","曹文涛",String.class) ; // 调用setter方法
setter(obj,"age",26,int.class); // 调用setter方法
System.out.print("姓名:") ;
getter(obj,"name");
System.out.print("年龄:") ;
getter(obj,"age");
}
/**
Objectobj:要操作的对象
Stringatt:要操作的属性
Objectvalue:要设置的属性内容
Class<?>type:要设置的属性类型
*/
publicstatic void setter(Object obj,String att,Object value,Class<?> type){
try{
Methodmet = obj.getClass().getMethod("set"+initStr(att),type) ; // 得到setter方法
met.invoke(obj,value); // 设置setter的内容
}catch(Exceptione){
e.printStackTrace();
}
}
publicstatic void getter(Object obj,String att){
try{
Methodmet = obj.getClass().getMethod("get"+initStr(att)) ; // 得到setter方法
System.out.println(met.invoke(obj)); // 调用getter取得内容
}catch(Exceptione){
e.printStackTrace();
}
}
publicstatic String initStr(String old){ // 将单词的首字母大写
Stringstr = old.substring(0,1).toUpperCase() + old.substring(1) ;
returnstr ;
}
};
通过反射调用属性
如果要操作一个类中的属性,则也可以通过Filed完成:
package org.cwt.demo15.invokedemo ;
import java.lang.reflect.Field ;
public class InvokeFieldDemo{
publicstatic void main(String args[]) throws Exception{
Class<?>c1 = null ;
Objectobj = null ;
c1= Class.forName("org.cwt.demo15.Person") ; // 实例化Class对象
obj= c1.newInstance() ;
FieldnameField = null ;
FieldageField = null ;
nameField= c1.getDeclaredField("name") ; //取得name属性
ageField= c1.getDeclaredField("age") ; //取得name属性
nameField.setAccessible(true); // 此属性对外部可见
ageField.setAccessible(true); // 此属性对外部可见
nameField.set(obj,"曹文涛") ; // 设置name属性内容
ageField.set(obj,26); // 设置age属性内容
System.out.println("姓名:" + nameField.get(obj)) ;
System.out.println("年龄:" + ageField.get(obj)) ;
}
};
通过反射操作数组
实例:
package org.cwt.demo15.invokedemo ;
import java.lang.reflect.Array ;
public class ClassArrayDemo{
publicstatic void main(String args[]) throws Exception{
inttemp[] = {1,2,3} ;// 声明一整型数组
Class<?>c = temp.getClass().getComponentType() ; //取得数组的Class对象
System.out.println("类型:" + c.getName()) ; // 取得数组类型名称
System.out.println("长度:" + Array.getLength(temp)) ;
System.out.println("第一个内容:" + Array.get(temp,0)) ;
Array.set(temp,0,6);
System.out.println("第一个内容:" + Array.get(temp,0)) ;
}
};
实例:通过反射实现对数组中元素的操作
package org.cwt.demo15.invokedemo ;
import java.lang.reflect.Array ;
public class ChangeArrayDemo{
publicstatic void main(String args[]) throws Exception{
inttemp[] = {1,2,3} ;// 声明一整型数组
intnewTemp[] = (int []) arrayInc(temp,5) ; //重新开辟空间5
print(newTemp);
System.out.println("\n-------------------------");
Stringt[] = {"cwt","mldn","mldnjava"} ;
Stringnt[] = (String [])arrayInc(t,8) ;
print(nt);
}
publicstatic Object arrayInc(Object obj,int len){
Class<?>c = obj.getClass() ;
Class<?>arr = c.getComponentType() ; // 得到数组的
ObjectnewO = Array.newInstance(arr,len) ; // 开辟新的大小
intco = Array.getLength(obj) ;
System.arraycopy(obj,0,newO,0,co); // 拷贝内容
returnnewO ;
}
publicstatic void print(Object obj){ // 数组输出
Class<?>c = obj.getClass() ;
if(!c.isArray()){ // 判断是否是数组
return;
}
Class<?>arr = c.getComponentType() ;
System.out.println(arr.getName()+"数组的长度是:" +Array.getLength(obj)) ; // 输出数组信息
for(inti=0;i<Array.getLength(obj);i++){
System.out.print(Array.get(obj,i)+ "、") ; // 通过Array输出
}
}
};
动态代理
代理设计:一个操作的接口有两个子类,其中一个是真实操作的实现类,另外一个是代理类,代理类实现类要完成比真实操作类更多的内容。
实例:通过Proxy类、类加载器完成动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy ;
import java.lang.reflect.Method ;
interface Subject{
publicString say(String name,int age) ; //定义抽象方法say
}
class RealSubject implements Subject{ // 实现接口
publicString say(String name,int age){
return"姓名:" +name + ",年龄:" +age ;
}
};
class MyInvocationHandler implementsInvocationHandler{
privateObject obj ;
publicObject bind(Object obj){
this.obj= obj ; // 真实主题类
returnProxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}
publicObject invoke(Object proxy,Method method,Object[] args) throws Throwable{
Objecttemp = method.invoke(this.obj,args) ; //调用方法
returntemp ;
}
};
public class DynaProxyDemo{
publicstatic void main(String args[]){
Subjectsub = (Subject)new MyInvocationHandler().bind(new RealSubject()) ;
Stringinfo = sub.say("曹文涛",26) ;
System.out.println(info);
}
};
工厂设计模式
实例:简单的工厂设计
package org.cwt.demo15.factorydemo01 ;
interface Fruit{
publicvoid eat() ; // 吃水果
}
class Apple implements Fruit{
publicvoid eat(){ // 覆写eat()方法
System.out.println("**吃苹果");
}
};
class Orange implements Fruit{
publicvoid eat(){
System.out.println("**吃橘子") ;
}
};
class Factory{
publicstatic Fruit getInstance(String className){
Fruitfruit = null ;
try{
fruit= (Fruit)Class.forName(className).newInstance() ;
}catch(Exceptione){
e.printStackTrace();
}
returnfruit ;
}
};
public class FactoryDemo01{
publicstatic void main(String args[]){
Fruitf = Factory.getInstance("org.cwt.demo15.factorydemo01.Apple") ;
if(f!=null){
f.eat();
}
}
};
实例:通过反射完成工厂设计
package org.cwt.demo15.factorydemo02 ;
import java.util.Properties ;
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.FileInputStream ;
interface Fruit{
publicvoid eat() ; // 吃水果
}
class Apple implements Fruit{
publicvoid eat(){ // 覆写eat()方法
System.out.println("**吃苹果");
}
};
class Orange implements Fruit{
publicvoid eat(){
System.out.println("**吃橘子") ;
}
};
class Init{
publicstatic Properties getPro(){
Propertiespro = new Properties() ;
Filef = new File("d:\\fruit.properties") ; // 找到属性文件
try{
if(f.exists()){ // 文件存在
pro.load(newFileInputStream(f)) ; // 读取属性
}else{
pro.setProperty("apple","org.cwt.demo15.factorydemo02.Apple");
pro.setProperty("orange","org.cwt.demo15.factorydemo02.Orange");
pro.store(newFileOutputStream(f),"FRUIT CLASS") ;
}
}catch(Exceptione){}
returnpro ;
}
};
class Factory{
publicstatic Fruit getInstance(String className){
Fruitfruit = null ;
try{
fruit= (Fruit)Class.forName(className).newInstance() ;
}catch(Exceptione){
e.printStackTrace();
}
returnfruit ;
}
};
public class FactoryDemo02{
publicstatic void main(String args[]){
Propertiespro = Init.getPro() ;
Fruitf = Factory.getInstance(pro.getProperty("apple")) ;
if(f!=null){
f.eat();
}
}
};
其中要建立配置文件:
fruit.properties:
apple = org.cwt.demo15.factorydemo02.Apple orange = org.cwt.demo15.factorydemo02.Orange |