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

java反射实例详解

2013-03-27 16:24 411 查看
本文先讲java反射的示例代码,希望看了代码以及分析对你有所帮助。

【案例1】通过一个对象获得完整的包名和类名
package org.shen.own;

import java.util.Enumeration;

import java.util.HashMap;

import java.util.Hashtable;

public class Hash {

...

}

package org.shen.own;

public class Reflect {

public static void main(String[] args) {

Hash hash = new Hash();

System.out.println(hash.getClass().getName());

}

}

程序运行结果:org.shen.own.Hash

补充一句:所有类的对象其实都是Class的实例。

【案例2】实例化Class类对象
Hash代码



package org.shen.own;

public class Reflect {

public static void main(String[] args) {

Class<?> hash1 = null;

Class<?> hash2 = null;

Class<?> hash3 = null;

try {

hash1 = Class.forName("org.shen.own.Hash"); //返回与带有给定字符串名的类或接口相关联的 Class 对象

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

hash2 = new Hash().getClass();

hash3 = Hash.class;

System.out.println(hash1.getName());

System.out.println(hash2.getName());

System.out.println(hash3.getName());

}

}

运行结果:

org.shen.own.Hash

org.shen.own.Hash

org.shen.own.Hash

【案例3】通过Class实例化其他类的对象
Person代码



package org.shen.own;

public class Person {

private int age;

private String name;

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "Person [age=" + age + ", name=" + name + "]";

}

}

Reflect代码



package org.shen.own;

public class Reflect {

public static void main(String[] args) {

Class<?> demo = null;

try {

demo = Class.forName("org.shen.own.Person");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Person person = null;

try {

person = (Person)demo.newInstance();//这里不实例化 会报空指针异常

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

person.setAge(20);

person.setName("shen");

System.out.println(person);

}

}

输出结果:Person [age=20, name=shen]

但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误:

Person构造函数代码



public Person(int age, String name) {

super();

this.age = age;

this.name = name;

}

如下错误:

错误代码



java.lang.InstantiationException: org.shen.own.Person

at java.lang.Class.newInstance0(Class.java:340)

at java.lang.Class.newInstance(Class.java:308)

at org.shen.own.Reflect.main(Reflect.java:13)

Exception in thread "main" java.lang.NullPointerException

at org.shen.own.Reflect.main(Reflect.java:19)

所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数

【案例】通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)
示例代码



package org.shen.own;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

public class Reflect {

public static void main(String[] args) {

Class<?> demo = null;

try {

demo = Class.forName("org.shen.own.Person");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Person per1 = null;

Person per2 = null;

Person per3 = null;

Person per4 = null;

Constructor<?>[] cons = demo.getConstructors();//获取实体类的构造函数 共有四个

int i;

for(i=0;i<cons.length;i++){

System.out.println(cons[i]);

}

try {

per1 = (Person) cons[0].newInstance(20);

per2 = (Person) cons[1].newInstance();

per3 = (Person) cons[2].newInstance("shenyc");

per4 = (Person) cons[3].newInstance(20,"shenyc");

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

System.out.println(per1);

System.out.println(per2);

System.out.println(per3);

System.out.println(per4);

}

}

运行结果:

public org.shen.own.Person(int)

public org.shen.own.Person()

public org.shen.own.Person(java.lang.String)

public org.shen.own.Person(int,java.lang.String)

Person [age=20, name=null]

Person [age=0, name=null]

Person [age=0, name=shenyc]

Person [age=20, name=shenyc]

『案例』返回一个类实现的接口:
接口示例代码



package org.shen.own;

public class Person1 implements China{

public Person1(){}

public Person1(String sex){

this.sex = sex;

}

@Override

public void sayChina() {

System.out.println("say ,hello , china!");

}

@Override

public void sayHello(String name, int age) {

System.out.println(name + " --- " + age);

}

private String sex;

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

}

package org.shen.own;

public interface China {

public static final String name = "Shenyc";

public static int age = 20;

public void sayChina();

public void sayHello(String name,int age);

}

package org.shen.own;

public class Reflect {

public static void main(String[] args) {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Class<?> inters[] = cls.getInterfaces(); //拿到接口

int i=0;

for(;i<inters.length;i++){

System.out.println(inters[i]);

}

}

}

运行结果:interface org.shen.own.China

得到Person1的父类:

父类代码



package org.shen.own;

public class Reflect {

public static void main(String[] args) {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

System.out.println(cls.getSuperclass().getName());//拿到父类的名字

Class<?> inters[] = cls.getInterfaces(); //拿到接口

int i=0;

for(;i<inters.length;i++){

System.out.println(inters[i]);

}

}

}

【案例】:获得其他类中的全部构造函数
例子代码



package org.shen.own;

import java.lang.reflect.Constructor;

public class Reflect {

public static void main(String[] args) {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Constructor<?>[] cons = cls.getConstructors();

int i=0;

for(;i<cons.length;i++){

System.out.println(cons[i]);

}

}

}

运行结果:

public org.shen.own.Person1()

public org.shen.own.Person1(java.lang.String)

后面各个案例中都将使用Person1这个类。

下面这个例子我们就来获取修饰符
获取修饰符代码



package org.shen.own;

import java.lang.reflect.Constructor;

import java.lang.reflect.Modifier;

public class Reflect {

public static void main(String[] args) {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Constructor<?>[] cons = cls.getConstructors();

int i=0;

for(;i<cons.length;i++){

Class<?> params[] = cons[i].getParameterTypes();

System.out.print("构造方法:");

int mo = cons[i].getModifiers();//以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符。应该使用 Modifier 类对这些修饰符进行解码。

//System.out.println(mo); //1

System.out.print(Modifier.toString(mo)+" "); //public 得到修饰符public

System.out.print(cons[i].getName()); //得到构造函数的名字 pkg+calss 即 org.shen.own.Person1

System.out.print("(");

//拿参数

for(int j=0;j<params.length;++j){

//System.out.println(params[j]);

System.out.print(params[j].getName()+" arg"+i);

if(j<params.length-1){

System.out.print(",");

}

}

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

}

}

}

运行结果:

构造方法:public org.shen.own.Person1(){}

构造方法:public org.shen.own.Person1(java.lang.String arg1){}

有时候一个方法可以抛出异常,如下面的例子:
抛出异常的方法代码



package org.shen.own;

import java.lang.reflect.Method;

public class Reflect {

public static void main(String[] args) {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Method method[] = cls.getMethods();

int i=0;

for(;i<method.length;i++){

System.out.println(method[i]);

}

}

}

输出结果:

public void org.shen.own.Person1.sayChina() //Person1里面的方法

public void org.shen.own.Person1.sayHello(java.lang.String,int)//Person1里面的方法

public java.lang.String org.shen.own.Person1.getSex()//Person1里面的方法

public void org.shen.own.Person1.setSex(java.lang.String)//Person1里面的方法

public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException

public final void java.lang.Object.wait() throws java.lang.InterruptedException

public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException

public boolean java.lang.Object.equals(java.lang.Object)

public java.lang.String java.lang.Object.toString()

public native int java.lang.Object.hashCode()

public final native java.lang.Class java.lang.Object.getClass()

public final native void java.lang.Object.notify()

public final native void java.lang.Object.notifyAll()

【案例】接下来让我们取得其他类的全部属性吧,最后我讲这些整理在一起,也就是通过class取得一个类的全部框架
取得全部属性代码



package org.shen.own;

import java.lang.reflect.Field;

import java.lang.reflect.Modifier;

public class Reflect {

public static void main(String[] args) {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Field field[] = cls.getDeclaredFields(); //输出private java.lang.String org.shen.own.Person1.sex

Field f[] = cls.getFields(); //得到父类或者接口的字段 属性

for(int i=0;i<field.length;i++){

int mo = field[i].getModifiers();

String p = Modifier.toString(mo);

System.out.println(p);

System.out.println(field[i]);

}

for(int j=0;j<f.length;j++){

int mo = f[j].getModifiers();

String p = Modifier.toString(mo);

System.out.println(p);

System.out.println(f[j]);

}

}

}

运行结果:

private

private java.lang.String org.shen.own.Person1.sex

public static final

public static final java.lang.String org.shen.own.China.name

public static final

public static final int org.shen.own.China.age

【案例】其实还可以通过反射调用其他类中的方法:
通过发射调用其他类的方法代码



package org.shen.own;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

public class Reflect {

public static void main(String[] args) {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

try {

Method method = cls.getMethod("sayChina"); //invoke Person1's sayChina method

method.invoke(cls.newInstance());

System.out.println(method);

Method m = cls.getMethod("sayHello", String.class,int.class);

m.invoke(cls.newInstance(), "shenyc",20);

System.out.println(m);

} catch (SecurityException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

}

}

}

运行结果:

say ,hello , china!

public void org.shen.own.Person1.sayChina()

shenyc --- 20

public void org.shen.own.Person1.sayHello(java.lang.String,int)

【案例】调用其他类的set和get方法
调用其他类的set和get方法代码



package org.shen.own;

import java.lang.reflect.Method;

public class Reflect {

public static void main(String[] args) throws Exception {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Object o =cls.newInstance(); //Person1

setter(o,"Sex","shenyc",String.class);

getter(o,"Sex");

}

//使用Person1中的get方法

private static void getter(Object o,String attr) throws Exception{

Method method = o.getClass().getMethod("get"+attr);

System.out.println(method.invoke(o));

}

//使用Person1中的set方法

public static void setter(Object o,String att,String value,Class<?> type) throws Exception{

Method method = o.getClass().getMethod("set"+att, type);

method.invoke(o, value);

}

}

运行结果:shenyc

【案例】通过反射操作属性
通过反射操作属性代码



package org.shen.own;

import java.lang.reflect.Field;

public class Reflect {

public static void main(String[] args) throws Exception {

Class<?> cls = null;

try {

cls = Class.forName("org.shen.own.Person1"); //拿到Person1

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Object o = cls.newInstance();

Field field[] = cls.getDeclaredFields(); //本例只有一个字段属性 所以不再使用遍历了

field[0].setAccessible(true); //不设置可访问,那么回报错误:自己可以试试

field[0].set(o, "男");

System.out.println(field[0].get(o));

}

}

【案例】通过反射取得并修改数组的信息:
通过反射取得并修改数组的信息代码



package org.shen.own;

import java.lang.reflect.Array;

import java.lang.reflect.Modifier;

public class Reflect {

public static void main(String[] args) throws Exception {

int[] array = {1,2,3,4,5};

Class<?> cls = array.getClass().getComponentType(); //返回表示数组组件类型的 Class。如果此类不表示数组类,则此方法返回 null。

//System.out.println(cls); //输出int

//数组的修饰符有点意思,有时间大家可以去研究一下

System.out.println("数组类型:"+cls.getName()+ " 数组修饰符:"+Modifier.toString(cls.getModifiers()));

System.out.println("array's length:"+Array.getLength(array));

System.out.println("the first element of array:" + Array.get(array, 0));

Array.set(array, 0, 100);

System.out.println("修改后数组的第一个元素:"+Array.get(array, 0));

}

}

【案例】通过反射修改数组大小
通过反射修改数组大小代码



package org.shen.own;

import java.lang.reflect.Array;

public class Reflect {

public static void main(String[] args) throws Exception {

int[] array = {1,2,3,4,5,6,7,8,9};

int[] newArr = (int[]) modifyArrayLength(array, 15);

print(newArr);

System.out.println();

String[] arr = {"a","b","c"};

String[] newArrStr = (String[])modifyArrayLength(arr, 15);

print(newArrStr);

}

//修改数组的大小

public static Object modifyArrayLength(Object o,int length){

//使用反射先拿到数组

Class<?> c = o.getClass().getComponentType();

Object newObj = Array.newInstance(c, length); //新数组

int l = Array.getLength(o);

System.arraycopy(o, 0, newObj, 0, l);

return newObj;

}

//输出数组

public static void print(Object o){

if(o==null){

System.out.println("数组是空的");

return;

}

Class<?> cls = o.getClass();

if(!cls.isArray()){

System.out.println("你所输入的不是数组");

return;

}

System.out.println("数组的长度为:"+Array.getLength(o));

System.out.print("数组是: ");

for(int i=0;i<Array.getLength(o);i++){

System.out.print(Array.get(o, i)+",");

}

}

}

运行结果:

数组的长度为:15

数组是: 1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,

数组的长度为:15

数组是: a,b,c,null,null,null,null,null,null,null,null,null,null,null,null,

动态代理
【案例】首先来看看如何获得类加载器:
获得类加载器代码



package org.shen.own;

public class Test {

}

package org.shen.own;

public class Hello {

public static void main(String[] args) {

Test t = new Test();

System.out.println("类加载器:"+ t.getClass().getClassLoader().getClass().getName());

}

}

输出结果:

类加载器:sun.misc.Launcher$AppClassLoader

分析:

其实在Java中有三类加载器:

1.Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。

2.Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类

3.AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。

动态代理
如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。

动态代理

http://shenyuc629.iteye.com/blog/1697485

类的生命周期

在一个类编译完成之后,下一步就需要开始使用类,如果要使用一个类,肯定离不开JVM。在程序执行中JVM通过装载,链接,初始化这3个步骤完成。

类的装载是通过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,并且在堆区创建描述这个类的java.lang.Class对象。用来封装数据。 但是同一个类只会被类装载器装载以前

链接就是把二进制数据组装为可以运行的状态。

链接分为校验,准备,解析这3个阶段

校验一般用来确认此二进制文件是否适合当前的JVM(版本),

准备就是为静态成员分配内存空间,。并设置默认值

解析指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)

完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。

当没有任何引用指向Class对象时就会被卸载,结束类的生命周期

使用反射实现工厂模式
Apple 代码



package org.shen.factory;

public class Apple implements Fruit{

@Override

public void eat() {

System.out.println("我在吃苹果");

}

}

Banana 代码



[

package org.shen.factory;

public class Banana implements Fruit{

@Override

public void eat() {

System.out.println("我在吃香蕉");

}

}

/code]

<pre class="Fruit" name="code">package org.shen.factory;

public interface Fruit {

public abstract void eat();

}

</pre>

<br>

<br><pre class="FactoryReflect " name="code">package org.shen.factory.reflect;

import org.shen.factory.Fruit;

public class FactoryReflect {

public static Object getInstance(String name){

Fruit f = null;

try {

f = (Fruit) Class.forName(name).newInstance();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

return f;

}

}

</pre>

<br>

<br><pre class="TestRF " name="code">package org.shen.factory.reflect;

import org.shen.factory.Fruit;

public class TestRF {

public static void main(String[] args) {

Fruit f = (Fruit) FactoryReflect.getInstance("org.shen.factory.Apple");

if(f!=null){

f.eat();

}

}

}

</pre>

<br>

<br>现在就算我们添加任意多个子类的时候,工厂类就不需要修改。

<br>

<br>上面的代码虽然可以通过反射取得接口的实例,但是需要传入完整的包和类名。而且用户也无法知道一个接口有多少个可以使用的子类,所以我们通过属性文件的形式配置所需要的子类。

<br>

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