http://blog.csdn.net/dream_broken/article/details/8830489java
反射中,最基础的是对Class类的了解和使用。在JAVA中Object是一切类的父类,而getClass()方法是Object中定义的,以下spring
- public final native Class<?> getClass();
那么能够这么说,全部类的对象实际上都是Class类的实例。若是你对类加载及JVM方法区有所了解,这个应该很容易理解。数组
本文主要是写点代码认识Class类的一些经常使用方法。app

1.获取Class对象框架 在Class类中,只定义了个私有的构造方法,这意味着,没法经过new Class()方式建立一个Class对象。eclipse
虽然没法直接使用new Class()方式建立对象,可是Class类中提供了forName()方法,经过它仍然能够得到Class对象。ide
- public static Class<?> forName(String className)
- throws ClassNotFoundException {
- return forName0(className, true, ClassLoader.getCallerClassLoader());
- }
-
-
-
-
- public static Class<?> forName(String name, boolean initialize,
- ClassLoader loader)
- throws ClassNotFoundException
除了使用forName()方法得到Class对象外,上面说过了Object是全部类的父类,而Object中有getClass()方法,因此经过"类名.getClass()"也能够得到Class对象,也能够经过“类名.class"工具
- package test;
-
- public class A1 {
-
- }
-
-
-
-
-
- <span style="font-size:18px;">public class A2 {
-
- public static void main(String[] args){
- Class<?> c1=null;
- Class<?> c2=null;
- Class<?> c3=null;
- try {
- c1=Class.forName("test.A1");
- c2=A1.class;
- A1 a1=new A1();
- c3=a1.getClass();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- System.out.println("类路径:"+c1.getName());
- System.out.println("类路径:"+c2.getName());
- System.out.println("类路径:"+c3.getName());
- }
- }</span>
运行结果测试 类路径:test.A1 类路径:test.A1 类路径:test.A1ui 经过运行结果可知,3种实例化Class对象的方式是同样的,可是使用forName()是较为经常使用的一种(固然,若是使用Hibernate或spring等框架时,常常使用"类.class“方式传送一个JavaBean实体)。 下面先看过设计上比较丑陋的例子。
- <span style="font-size:18px;">package test;
-
-
-
-
-
- public interface Fruit {
- public void say();
- }
-
-
-
- package test;
-
-
-
-
- public class Apple implements Fruit {
- @Override
- public void say() {
- System.out.println("hello,I'm apple!");
- }
- }
-
-
-
-
-
-
-
- public class Banana implements Fruit {
-
- @Override
- public void say() {
- System.out.println("hello,I'm banana!");
- }
- }
-
-
-
-
- package test;
-
-
-
-
- public class FruitUtil {
-
- public static Fruit createFruit(String fruitName){
- if("apple".equalsIgnoreCase(fruitName)) return (Fruit)new Apple();
- if("banana".equalsIgnoreCase(fruitName)) return (Fruit)new Banana();
- return null;
- }
- }
-
-
-
- package test;
-
-
-
-
- public class Test {
-
- public static void main(String[] args){
- Fruit f=FruitUtil.createFruit("apple");
- if(f!=null) {
- f.say();
- }else{
- System.out.println("没有水果!");
- }
- }
- </span>}
运行结果 hello,I'm apple! 代码没错,运行结果也没错,我之因此说它丑陋,是从代码扩展性方面考虑。好比,若是我要再添加一种水果呢?那么就必须修改FruitUtil.createFruit()方法中的代码了,增长if判断。那若是我要新曾几十种水果呢?那是否是要写几十个if判断。。。。。做为一个接触JAVA两年的菜鸟的我,都以为代码设计不友好了,更别说修改原有代码对系统的危害了。那有没有一种方法,当新增水果时,不须要对原有代码作任何修改呢?有,这时,Class.forName()一声大哄,粉墨登场了。
- <span style="font-size:18px;">package test;
-
-
-
-
-
- public interface Fruit {
- public void say();
- }
-
-
- package test;
-
-
-
-
- public class Apple implements Fruit {
- @Override
- public void say() {
- System.out.println("hello,I'm apple!");
- }
- }
-
-
-
- package test;
-
-
-
-
- public class Banana implements Fruit {
-
- @Override
- public void say() {
- System.out.println("hello,I'm banana!");
- }
- }
-
-
- package test;
-
-
-
-
- public class FruitUtil {
-
- public static Fruit createFruit(String classPath)throws Exception{
- Fruit fruit=null;
- try {
- fruit=(Fruit)Class.forName(classPath).newInstance();
- } catch (Exception e) {
- e.printStackTrace();
- throw new Exception("建立水果失败!");
- }
- return fruit;
- }
- }
-
-
- package test;
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.util.Properties;
-
-
-
-
-
- public class Test {
-
- private final static String FRUIT_CONF_PATH=System.getProperty("user.dir");
- public static void main(String[] args){
- Properties p=new Properties();
- try {
-
- FileInputStream in=new FileInputStream(new File(FRUIT_CONF_PATH+File.separator+"bin"+File.separator+"fruit.properties"));
- p.load(in);
- String fruitClassPath=p.getProperty("apple");
- p.clear();
- in.close();
- Fruit f=FruitUtil.createFruit(fruitClassPath);
- f.say();
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("获取水果实例失败!");
- }
- }
- }</span>
fruit.properties配置文件
- apple=test.Apple
- banana=test.Banana
运行结果 hello,I'm apple! 这样改写后,之后有新增水果时,只要编写新增水果类,并再配置文件中配置新水果的类路径就OK了,原有的代码不须要修改。 这样的设计就具备很好的扩展性。 |
2.获取类中的成员变量 getFields():得到类(包括父类)的public成员变量 getDeclaredFields():得到类(不包括父类)的所有成员变量
- package test;
-
- public class A {
-
- public int n_A;
- private String s_A;
- protected double d_A;
- }
-
- package test;
-
- public class A1 extends A {
- public int n_A1;
- private String s_A1;
- protected double d_A1;
-
- }
-
- package test;
-
- import java.lang.reflect.Field;
-
- public class A2 {
- public static void main(String[] args){
- Class<?> c1=null;
- try {
- c1=Class.forName("test.A1");
- Field[] f1=c1.getFields();
- for(Field f:f1)
- System.out.println("A1(包括父类)类中public 成员变量:"+f.getName());
- System.out.println("获取A1(不包括父类)类中的全部成员变量::::::::");
- Field[] f2=c1.getDeclaredFields();
- for(Field f:f2)
- System.out.println("A1(不包括父类)类中的成员变量:"+f.getName());
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- }
运行结果 A1(包括父类)类中public 成员变量:n_A1 A1(包括父类)类中public 成员变量:n_A 获取A1(不包括父类)类中的全部成员变量:::::::: A1(不包括父类)类中的成员变量:n_A1 A1(不包括父类)类中的成员变量:s_A1 A1(不包括父类)类中的成员变量:d_A1 |
3.获取类中的方法 getMethods():获取类(包括父类)中的public方法(不包括构造方法) getDeclaredMethods():获取本类(不包括父类)中的全部方法(不包括构造方法) getConstructors():获取本类(不包括父类)中的全部public构造方法 考虑到篇幅问题,就不贴代码了。 |
4.实例化对象
- <span style="font-size:18px;">package test;
-
- public class A1 {
- private int n;
-
- public A1(){
- this.n=0;
- }
- public A1(int n){
- this.n=n;
- }
-
- public int getN() {
- return n;
- }
- public void setN(int n) {
- this.n = n;
- };
- }
-
-
- package test;
-
- import java.lang.reflect.Constructor;
-
- public class A2 {
- public static void main(String[] args){
- Class<?> c1=null;
- try {
- c1=Class.forName("test.A1");
- A1 a1=(A1)c1.newInstance();
- System.out.println("使用Class类中的newInstance()方法实例化,a1.n="+a1.getN());
- Constructor<?>[] con=c1.getConstructors();
- A1 a2=(A1)con[0].newInstance();
- System.out.println("使用Constructor类中的public T newInstance(Object ... initargs)方法实例化,a2.n="+a2.getN());
- A1 a3=(A1)con[1].newInstance(10);
- System.out.println("使用Constructor类中的public T newInstance(Object ... initargs)方法实例化,a3.n="+a3.getN());
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- }</span>
运行结果 使用Class类中的newInstance()方法实例化,a1.n=0 使用Constructor类中的public T newInstance(Object ... initargs)方法实例化,a2.n=0 使用Constructor类中的public T newInstance(Object ... initargs)方法实例化,a3.n=10 |
5.经过反射调用类中的方法
- <span style="font-size:18px;color:#000000;">package test;
-
- public class A {
-
- public void sayHello(){
- System.out.println("hello,world");
- }
- public void sayHello(String name){
- System.out.println("hello,"+name);
- }
- }
-
- package test;
-
- import java.lang.reflect.Method;
-
- public class Test01 {
-
- public static void main(String[] args){
- Class<?> c=null;
- try {
- c=Class.forName("test.A");
- A a=(A)c.newInstance();
- Method m1=c.getMethod("sayHello");
- m1.invoke(a);
- Method m2=c.getMethod("sayHello", String.class);
- m2.invoke(a, "everyOne");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }</span>
运行结果 hello,world hello,everyOne |
6.经过反射破坏类的封装性(给私有变量赋值并访问)
- <span style="font-size:18px;">package test;
-
- public class User {
-
- private String name;
- private int age;
- public String getName() {
- return name;
- }
- public int getAge() {
- return age;
- }
-
- }
-
-
- package test;
-
- import java.lang.reflect.Field;
-
-
-
-
- public class Test01 {
-
- public static void main(String[] args){
- Class<?> c=null;
- try {
- c=Class.forName("test.User");
- User user=(User)c.newInstance();
- Field name=c.getDeclaredField("name");
- Field age=c.getDeclaredField("age");
- name.setAccessible(true);
- age.setAccessible(true);
- name.set(user, "张三");
- age.set(user, 20);
- System.out.println("姓名:"+name.get(user)+" "+user.getName());
- System.out.println("年龄:"+age.get(user)+" "+user.getAge());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }</span>
运行结果 姓名:张三 张三 年龄:20 20 |