您的位置:首页 > 编程语言 > Java开发

java语言基础入门——反射机制实例

2016-08-07 15:18 681 查看
1、什么是反射呢?反射可以理解为在程序运行时获取对象类型信息的操作。它允许动态的发现和绑定类、方法、字段,甚至由其他语言产生的元素。运用反射可以做到列举对象所对应的类的详细信息,如访问修饰符,包名,类名,继承的父类和接口信息,以及类内部的所有成员变量,构造函数,成员函数,函数的修饰符,返回值,参数等信息,甚至还可以利用反射来创建对象,访问成员变量和函数。可以这么说,反射窥探到类的所有信息。

2、反射所需的类。反射很强大,但它用到的类并不多,主要有java.lang.Class类和java.lang.reflect包中的Field、Constructor、Method、Array类。

Class类:Class类的实例是表示正在运行的Java应用程序中的类和接口。可以这么理解,一个普通类是Class类的一个对象。

Filed类:提供有关接口或类的属性信息,以及对他的访问权限修饰符。反射的字段可能是一个类或接口的属性或实例属性。也就是说Filed用来反射类中的成员变量信息。

Constructor类:提供类的单个构造方法的信息以及对他的访问权限修饰符。也就是说Constructor用来反射类中的构造方法的信息。

Method类:提供关于类或接口上单独某个方法的信息,包括抽象方法,可以得到方法的访问修饰符,返回值类型,参数类型等信息。也就是说method类用来反射类的除构造方法以外的方法信息。

Array类:提供了动态创建数组和访问的数组的静态方法。该类的所有方法都为静态方法。

下面是反射操作的例子,包括了得到类的信息,成员变量,构造方法,成员方法;创建对象,调用方法,得到成员变量的值的操作。package reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import product.Producter;

class Book{
private int id;
protected String name;
public double price;
String type;
public Book() {
this(10001,"新华字典",30.3,"工具书");
}
public Book(int id,String name,double price,String type){
this.id=id;
this.name=name;
this.price=price;
this.type=type;
}
private Book(int id) {
this(10001,"新华字典",30.3,"工具书");
this.setId(id);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
private void setAll(int id,String name,double price,String type) {
this.setId(id);
this.setName(name);
this.setPrice(price);
this.setType(type);
}
public String toString(){
return "书名为:"+name+" 编码为:"+id+" 类型为:"+type+" 价格为:"+price;
}
}
public class ClassDemo {

/**
* 三种方式可以获得Class对象的方式
*/
public static void getClassObject() {
//调用Object类的getClass()方法类获得Class对象,这是最常用的获得Class对象的方法
Book book1=new Book();
System.out.println(book1.getClass()); //显示形式:class 包名.类名

//使用Class类的forName()静态方法获得与字符串参数相对应的Class对象
try {
//Class class1=Class.forName("java.lang.String");
Class class1=Class.forName("reflection.Book");
//字符串必须是类或接口的全限定名,所以带上包名
System.out.println(class1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

//使用类型名.class获取该类型对应的Class对象
Class class2=Double[].class;
System.out.println(class2);
}

/**
* 获取Class对象的类型信息
*/
public static void getClassInformation(){
Book book2=null;
book2=new Book(321, "笑傲江湖", 44.5, "武侠");
Class class4=book2.getClass();//获取class对象
String packageName = class4.getPackage().getName();//获取类的包名
System.out.println("包名为:"+packageName);
String mod =Modifier.toString(class4.getModifiers());//获取类的修饰符
//.getModifiers()返回的是个整数,调用Modifier的toString方法来转化为String类型
System.out.println("类的修饰符为:"+mod);
String className=class4.getName();//获取全限定名(数组类型会产生奇怪字符)
System.out.println("类的全限定名称为:"+className);
Class superClass = class4.getSuperclass();//获取父类
System.out.println("父类为:"+superClass);
Class[] interfaces=class4.getInterfaces();//获取接口
System.out.println("接口为:"+interfaces);

}

/**
* 获取Class对象的类的成员变量的信息
*/
public static void getClassmember(){
Book book2=null;
book2=new Book(321, "笑傲江湖", 44.5, "武侠");
Class class4=book2.getClass();//获取class对象
Field [] fields=class4.getDeclaredFields();//获取所有成员变量
Field []fields2=class4.getFields();//获取public修饰的成员变量
System.out.println("所有成员变量为:");
for(Field ff: fields){
String moString=Modifier.toString(ff.getModifiers());//修饰符
Class classType=ff.getType();//数据类型
String name=ff.getName();//字段名
if (classType.isArray()) {//如果是数组类型需要特别处理一下
String arrType=classType.getComponentType().getName()+"[]";
System.out.println(moString+"修饰的"+arrType+"类型的"+name);
}else {
System.out.println(moString+"修饰的"+classType+"类型的"+name);
}
}
System.out.println("其中用public修饰的有:");
for (Field ff:fields2) {
System.out.println(ff.getName());

}
}

/**
* 获取Class对象的类的构造方法的信息
*/
public static void getClassConstructor(){
Book book2=null;
book2=new Book(321, "笑傲江湖", 44.5, "武侠");
Class class4=book2.getClass();//获取class对象
Constructor[] constructors=class4.getConstructors();//获取该Class对象使用所有public修饰的构造方法
Constructor[] constructors2=class4.getDeclaredConstructors();//获取该class对象所对应类的所有构造方法
System.out.println("class4所属类的构造方法的信息为:");
for (Constructor cc: constructors2) {
String name=cc.getName();//获取构造方法名称
String modifier =Modifier.toString(cc.getModifiers());//获取访问修饰符
System.out.print(name+" "+modifier+" (");
Class [] paramTypes=cc.getParameterTypes();//得到方法的参数列表
for (int i = 0; i < paramTypes.length; i++) {
if (i>0) {
System.out.print(",");
}
if (paramTypes[i].isArray()) {//参数类型为数组时
System.out.print(paramTypes[i].getComponentType().getName()+"[]");
//getComponentType()为数组时返回数组的类型,不为数组返回空
}else {
System.out.print(paramTypes[i].getName());
}

}
System.out.println(")");
}

}

/**
* 获取类的成员方法的信息
*/
public static void getClassmethod(){
Book book2=null;
book2=new Book(321, "笑傲江湖", 44.5, "武侠");
Class class4=book2.getClass();//获取class对象
System.out.println("class4对象实例的所属类的成员方法信息为:");
Method[] methods1=class4.getMethods();
//获取Class对象实例对应的类的所有用public修饰的成员方法
Method[] methods=class4.getDeclaredMethods();
//获取Class对象实例的类的所有成员方法
for (Method mm:methods1) {
String modifier=Modifier.toString(mm.getModifiers());//访问修饰符
Class returnType=mm.getReturnType();//返回类型
if (returnType.isArray()) {//如果是数组类型需要特别处理
String arrType= returnType.getComponentType().getName()+"[]";
System.out.print(" "+ modifier+ " "+arrType+" "+mm.getName()+" (");
}else {
System.out.print(" "+ modifier+ " "+returnType+" "+mm.getName()+" (");
}
Class [] paramTypes=mm.getParameterTypes();//得到方法的参数列表
for (int i = 0; i < paramTypes.length; i++) {
if (i>0) {
System.out.print(",");
}
if (paramTypes[i].isArray()) {//参数类型为数组时
System.out.print(paramTypes[i].getComponentType().getName()+"[]");
//getComponentType()为数组时返回数组的类型,不为数组返回空
}else {
System.out.print(paramTypes[i].getName());
}

}
System.out.println(")");
}

}

/**
* 通过反射来创建类的对象—-通过无参数的构造方法
* @param args
*/
public static Object createNoneParameterObject(String className){
Object object=null;
try {
//加载指定名称的类,获取对应的Class对象,然后调用无参数的构造方法创造一个对象
object=Class.forName(className).newInstance();

} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
e.printStackTrace();
}
return object;
}

/**
* 通过反射来创建类的对象—-通过有参数的构造方法
* 第一步:获取指定类对应的Class对象
* 第二步:通过Class对象获取满足指定参数类型要求的构造方法类对象
* 第三步:调用指定Constructor对象类型的newInstance方法,传入对应的参数值,创建呢对象
* @param args
*/
public static Object createHaveParameterObject(String className) {
Object object=null;
Class class1;
try {
class1 = Class.forName(className);
Constructor constructor=class1.getConstructor(
int.class,java.lang.String.class,double.class,java.lang.String.class);
object=constructor.newInstance(100,"三国演义",33.2,"历史");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {

b5f6
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return object;
}

/**
* 使用反射来调用方法
* 使用反射可以取得指定类的指定方法的对象代表
* 方法的对象代表就是前面介绍的java.lang.reflect.Method类的实例,
* 通过Method类的invode方法可以动态的调用这个方法
* @param args
*/
public static void callMethods(String classNmae) {
try {
Class class1=Class.forName(classNmae);
Book book=(Book)class1.newInstance();//利用无参构造方法创建一个Book对象
//获取名为setName,带一个String的成员方法所对应的对象代表
Method method1=class1.getDeclaredMethod("setName",String.class);
//在book对象上调用setName,并传值给它,返回值为空
Object returnType=method1.invoke(book, "西游记");
System.out.println("通过反射访问setName函数,其返回值为:"+returnType);
//获取名为toString不带参数的成员方法对应的参数列表
Method method2=class1.getDeclaredMethod("toString");
method2.setAccessible(true);//取消访问检查
//在book对象上调用toString方法
String string=(String) method2.invoke(book);
System.out.println(string);

} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

}

/**
* 通过反射访问成员变量的值
* 通过反射可以取得类的成员变量的对象代表,成员变量的对象代表是java.lang.reflect.Field类的实例
* 可以使用它的get和set方法来对成员变量获取或设置它的值
* @param args
*/
public static void getmember(String className) {

try {
Class class1 = Class.forName(className);
Book book=(Book)class1.newInstance();//使用无参构造方法创建对象
//调取私有属性id
Field idfield=class1.getDeclaredField("id");
idfield.setAccessible(true);//取消对本字段的访问检查
idfield.setInt(book, 202);
//将book对象的IDfield成员变量设置为202
System.out.println("设置后的Id为:"+idfield.getInt(book));
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (InstantiationException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (SecurityException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}

}
public static void main(String[] args) {
ClassDemo.getClassObject();//三种方式可以获得Class对象的方式
ClassDemo.getClassInformation();//获取Class对象的类型信息
ClassDemo.getClassmember();//获取Class对象的类的成员变量的信息
ClassDemo.getClassConstructor();//获取Class对象的类的构造方法的信息
ClassDemo.getClassmethod();//获取类的成员方法的信息
//通过反射来创建类的对象—-通过无参数的构造方法
Book book=(Book)ClassDemo.createNoneParameterObject("reflection.Book");//带上包名
System.out.println("通过反射创建类的对象(无参构造方法)为:"+"\n"+book.toString());
//通过反射来创建类的对象—-通过有参数的构造方法
Book book2=(Book)ClassDemo.createHaveParameterObject("reflection.Book");//带上包名
System.out.println("通过反射创建类的对象(有参构造方法)为:"+"\n"+book2.toString());
ClassDemo.callMethods("reflection.Book");//通过Method类的invode方法可以动态的调用这个方法
ClassDemo.getmember("reflection.Book");//通过反射访问成员变量的值
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: