java 反射技术,
java 反射技术,
【案例1】通过一个对象获得完整的包名和类名
package Reflect;
/**
* 通过一个对象获得完整的包名和类名
* */
class Demo{
//other codes...
}
class hello{
public static void main(String[] args) {
Demo demo=new Demo();
System.out.println(demo.getClass().getName());
}
}
【运行结果】:Reflect.Demo
添加一句:所有类的对象其实都是Class的实例。
【案例2】实例化Class类对象
package Reflect;
class Demo{
//other codes...
}
class hello{
public static void main(String[] args) {
Class<?> demo1=null;
Class<?> demo2=null;
Class<?> demo3=null;
try{
//一般尽量采用这种形式
demo1=Class.forName("Reflect.Demo");
}catch(Exception e){
e.printStackTrace();
}
demo2=new Demo().getClass();
demo3=Demo.class;
System.out.println("类名称 "+demo1.getName());
System.out.println("类名称 "+demo2.getName());
System.out.println("类名称 "+demo3.getName());
}
}
//一般尽量采用这种形式,可以在编译期进行检查
demo1=Class.forName(
"Reflect.Demo"
);
关于 Class<?>
Class
is
a parametrizable class, hence you can use the syntax Class<T>
where
T is a type. By writing Class<?>
,
you're declaring a Class
object
which can be of any type (?
is
a wildcard). TheClass
type
is a type that contains metainformation about a class.
It's always good practice to refer to a generic type by specifying his specific type, by using Class<?>
you're
respecting this practice (you're aware of Class
to
be parametrizable) but you're not restricting your parameter to have a specific type.
Reference about Generics and Wildcards:http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html
Reference about Class object and reflection (the feature of Java language used to introspect itself):http://java.sun.com/developer/technicalArticles/ALT/Reflection/
http://stackoverflow.com/questions/9921676/what-does-class-mean-in-java
class 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 "["+this.name+" "+this.age+"]";
}
private String name;
private int age;
}
class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Person per=null;
try {
per=(Person)demo.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
per.setName("Rollen");
per.setAge(20);
System.out.println(per);
}
}
但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误:
比如我定义了一个构造函数:
public Person(String name, int age) {
this.age=age;
this.name=name;
}
然后继续运行上面的程序,会出现:
java.lang.InstantiationException: Reflect.Person
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at Reflect.hello.main(hello.java:39)
Exception in thread "main" java.lang.NullPointerException
at Reflect.hello.main(hello.java:47)
所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数。
【案例4】通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)
import java.lang.reflect.Constructor;
class Person{
public Person() {
}
public Person(String name){
this.name=name;
}
public Person(int age){
this.age=age;
}
public Person(String name, int age) {
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString(){
return "["+this.name+" "+this.age+"]";
}
private String name;
private int age;
}
class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Person per1=null;
Person per2=null;
Person per3=null;
Person per4=null;
//取得全部的构造函数
Constructor<?> cons[]=demo.getConstructors();
try{
per1=(Person)cons[0].newInstance();
per2=(Person)cons[1].newInstance("Rollen");
per3=(Person)cons[2].newInstance(20);
per4=(Person)cons[3].newInstance("Rollen",20);
}catch(Exception e){
e.printStackTrace();
}
System.out.println(per1);
System.out.println(per2);
System.out.println(per3);
System.out.println(per4);
}
}
PS: 这里面的程序最好自己打印一下构造函数的顺序,因为可能构造函数和上面的不一样,加上一下的代码打印一下,看看构造数组里面构造函数的顺序是什么?
for(Constructor<?> constructor : cons)
{
System.out.println(constructor.toString());
}
【案例5】 返回一个类实现的接口
interface China{
public static final String name="Rollen";
public static int age=20;
public void sayChina();
public void sayHello(String name, int age);
}
class Person implements China{
public Person() {
}
public Person(String sex){
this.sex=sex;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public void sayChina(){
System.out.println("hello ,china");
}
@Override
public void sayHello(String name, int age){
System.out.println(name+" "+age);
}
private String sex;
}
class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
//保存所有的接口
Class<?> intes[]=demo.getInterfaces();
for (int i = 0; i < intes.length; i++) {
System.out.println("实现的接口 "+intes[i].getName());
}
}
}
主要的获取类的接口的方法代码:
demo = Class.forName("test8.Person");
Class<?> intes[] = demo.getInterfaces();
for (int i = 0; i < intes.length; i++)
{
System.out.println("实现的接口 " + intes[i].getName());
}
【案例6】:取得其他类中的父类
Class<?> temp=demo.getSuperclass();
System.out.println("继承的父类为: "+temp.getName());
【案例7】:获得其他类中的全部构造函数
Constructor<?>cons[]=demo.getConstructors();
for (int i = 0; i < cons.length; i++) {
System.out.println("构造方法: "+cons[i]);
}
【案例8】 : 获得构造函数的各个部分,例如构造函数名,构造函数的参数,构造函数的修饰符等等。
class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Constructor<?>cons[]=demo.getConstructors();
for (int i = 0; i < cons.length; i++) {
Class<?> p[]=cons[i].getParameterTypes();
System.out.print("构造方法: ");
int mo=cons[i].getModifiers();
System.out.print(Modifier.toString(mo)+" ");
System.out.print(cons[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("){}");
}
}
}
获取构造函数的修饰符:
int
mo=cons[i].getModifiers();
System.out.print(Modifier.toString(mo)+
"
"
);
获取构造函数的名字: System.out.print(cons[i].getName())
获取构造函数的参数:
Class<?>
p[]=cons[i].getParameterTypes();
打印参数:
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(
"){}"
);
【案例9】 获取方法的异常信息
Class<?> exce[]=method[i].getExceptionTypes();
if(exce.length>0){
System.out.print(") throws ");
for(int k=0;k<exce.length;++k){
System.out.print(exce[k].getName()+" ");
if(k<exce.length-1){
System.out.print(",");
}
}
}else{
System.out.print(")");
}
打印构造函数的代码:
Class<?> exce[] = method[i].getExceptionTypes();
if (exce.length > 0)
{
System.out.print(") throws ");
for (int k = 0; k < exce.length; ++k)
{
System.out.print(exce[k].getName() + " ");
if (k < exce.length - 1)
{
System.out.print(",");
}
}
} else
{
System.out.print(")");
}
System.out.println();
【案例10】 取得类的属性
class hello {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("Reflect.Person");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("===============本类属性========================");
// 取得本类的全部属性
Field[] field = demo.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 权限修饰符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = field[i].getType();
System.out.println(priv + " " + type.getName() + " "
+ field[i].getName() + ";");
}
System.out.println("===============实现的接口或者父类的属性========================");
// 取得实现的接口或者父类的属性
Field[] filed1 = demo.getFields();
for (int j = 0; j < filed1.length; j++) {
// 权限修饰符
int mo = filed1[j].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = filed1[j].getType();
System.out.println(priv + " " + type.getName() + " "
+ filed1[j].getName() + ";");
}
}
}
1. 取得本类的全部属性,包括public,private等。
Field[]
field = demo.getDeclaredFields();
2. 取得本类的或者是父类的public 属性
Field[]
filed1 = demo.getFields();
通过循环可取得每一个属性的 权限修饰符,属性名,属性的类型
属性的权限修饰符:
int
mo
= filed1[j].getModifiers();
String
priv = Modifier.toString(mo);
属性的类型:
Class<?>
type = filed1[j].getType();
属性的名字:
filed1[j].getName()
【案例11】
通过反射调用类中的方法
class hello {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("Reflect.Person");
} catch (Exception e) {
e.printStackTrace();
}
try{
//调用Person类中的sayChina方法
Method method=demo.getMethod("sayChina");
method.invoke(demo.newInstance());
//调用Person的sayHello方法
method=demo.getMethod("sayHello", String.class,int.class);
method.invoke(demo.newInstance(),"Rollen",20);
}catch (Exception e) {
e.printStackTrace();
}
}
}
调用特定的方法:
//1. 通过方法名以及参数得到指定的方法
Method
method=demo.getMethod(
"sayChina"
);
method=demo.getMethod(
"sayHello"
,
String.
class
,
int
.
class
);
//2. 通过invoke调用特定的方法
method.invoke(demo.newInstance());
method.invoke(demo.newInstance(),
"Rollen"
,
20
);
【案例12】调用其他类的set和get方法
这里面是利用反射得到通用的getter和setter方法
class hello {
public static void main(String[] args) {
Class<?> demo = null;
Object obj=null;
try {
demo = Class.forName("Reflect.Person");
} catch (Exception e) {
e.printStackTrace();
}
try{
obj=demo.newInstance();
}catch (Exception e) {
e.printStackTrace();
}
setter(obj,"Sex","男",String.class);
getter(obj,"Sex");
}
/**
* @param obj
* 操作的对象
* @param att
* 操作的属性
* */
public static void getter(Object obj, String att) {
try {
Method method = obj.getClass().getMethod("get" + att);
System.out.println(method.invoke(obj));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param obj
* 操作的对象
* @param att
* 操作的属性
* @param value
* 设置的值
* @param type
* 参数的属性
* */
public static void setter(Object obj, String att, Object value,
Class<?> type) {
try {
Method method = obj.getClass().getMethod("set" + att, type);
method.invoke(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}// end class
这里面主要的setter的关键点:
Method
method = object.getClass().getMethod("set" + att, type);
method.invoke(object, value);
object 这里面用到了多态,利用 getclass得到多态类的一个class对象,class对象可以调用getmethod方法,里面放的参数 1. 是方法名,2.是 方法需要的参数
然后运用method.invoke去实际调用某个对象的方法,参数 1. object 是通过class对象newinstance出来的类的对象 2. 调用方法的参数。
这里面主要的gettter的关键点:
Method method
= object.getClass().getMethod("get"+att);
System.out.println(method.invoke(object));
分析和上面的相同
【案例13】 通过反射操作属性
关键点:
1. 得到某个属性
Field field = demo.getDeclaredField("sex");
2.对于private的属性,要设置成可accesss
field.setAccessible(true);
3.调用属性的get或者set方法
field.set(obj, "男");
System.out.println(field.get(obj));
【案例14】通过放射取得并修改数组的信息
Class<?> demo = temp.getClass().getComponentType();
System.out.println("数组类型: " + demo.getName());
System.out.println("数组长度 " + Array.getLength(temp));
System.out.println("数组的第一个元素: " + Array.get(temp, 0));
Array.set(temp, 0, 100);
System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
注意:里面有一个Array是放射里面用来操作数组的
Array.getLength(temp)); 得到数组的长度
Array.get(temp, 0) 得到数组的某一个元素
Array.set(temp, 0, 100); 设置某一个数组的某个元素为一个新值
下面的开始反射的应用,关于动态代理的知识
【案例15】如何获得类加载器
class test{
}
class hello{
public static void main(String[] args) {
test t=new test();
System.out.println("类加载器 "+t.getClass().getClassLoader().getClass().getName());
}
}
其实在java中有三种类类加载器。
1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类
3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
【案例16】动态代理
import java.lang.reflect.*;
//定义项目接口
interface Subject {
public String say(String name, int age);
}
// 定义真实项目
class RealSubject implements Subject {
@Override
public String say(String name, int age) {
return name + " " + age;
}
}
class MyInvocationHandler implements InvocationHandler {
private Object obj = null;
public Object bind(Object obj) {
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object temp = method.invoke(this.obj, args);
return temp;
}
}
class hello {
public static void main(String[] args) {
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject) demo.bind(new RealSubject());
String info = sub.say("Rollen", 20);
System.out.println(info);
}
}
反射机制的应用有java的动态代理,关于java 的动态代理可以看另一篇文章。
相关文章
- 暂无相关文章
用户点评