Java 反射机制

根据李兴华的视频整理的

大致是先得到Class的类的对象,然后在用这个对象调用newInstance方法创建实例,就可以对实例进行操作了

Java反射的源头是Class这个类:

public final class Class<T>extends Objectimplements Serializable, GenericDeclaration, Type, AnnotatedElement

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(booleanbytecharshortintlongfloatdouble)和关键字 void 也表示为 Class 对象。

Class 没有公共构造方法Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

以下示例使用 Class 对象来显示对象的类名:

     void printClassName(Object obj) {
         System.out.println("The class of " + obj +
                            " is " + obj.getClass().getName());
     }

 实例化Class对象有3中方法:

1、Class.forName()

public static Class<?> forName(String className)
                        throws ClassNotFoundException

返回与带有给定字符串名的类或接口相关联的 Class 对象。

这个最常用啦,比如说java连接数据库加载驱动时:Class.forName("com.mysql.jdbc.Driver") ;  字符串为 包名.类名

2、类名.class

3、对象.getClass()

得到Class类的对象后就可以调用newInstance方法创建实例啦

public T newInstance()
              throws InstantiationException,
                     IllegalAccessException
创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。如果该类尚未初始化,则初始化这个类。 

注意:类中必须提供无参构造函数(如果不写构造函数,那么类本身就提供无参构造函数,如果写了构造函数,那么那个默认的就没有了),而且那个构造函数还得是可以访问的,如果是私有的话,那就不行啦

 1 package yxy;
 2 
 3 class Person{
 4     private String name;
 5     public String getName() {
 6         return name;
 7     }
 8 
 9     public void setName(String name) {
10         this.name = name;
11     }
12     private Person(){
13         this.setName("crane");
14     }
15     
16     public String toString(){
17         return "name= "+this.getName();
18     }
19 }
20 
21 public class Test {
22     
23     public static void main(String[] args) {
24         // TODO Auto-generated method stub
25         try {
26             System.out.println(Class.forName("yxy.Person").newInstance());
27         } catch (InstantiationException e) {
28             // TODO Auto-generated catch block
29             e.printStackTrace();
30         } catch (IllegalAccessException e) {
31             // TODO Auto-generated catch block
32             e.printStackTrace();
33         } catch (ClassNotFoundException e) {
34             // TODO Auto-generated catch block
35             e.printStackTrace();
36         }
37     }
38 
39 
40 }
java.lang.IllegalAccessException: Class yxy.Test can not access a member of class yxy.Person with modifiers "private"
    at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at yxy.Test.main(Test.java:26)

如果把12行改为public Person(){

则运行结果为:name= crane

如果是带参的可访问的构造函数也是不行的,

不过可以用getConstructors来整(有点儿像病句哇)

getConstructors()返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。

 1 package yxy;
 2 
 3 import java.lang.reflect.Constructor;
 4 
 5 class Person{
 6     private String name;
 7     public String getName() {
 8         return name;
 9     }
10 
11     public void setName(String name) {
12         this.name = name;
13     }
14     public Person(){
15         this.setName("crane");
16     }
17     public Person(String name){
18         this.setName(name);
19     }
20     public String toString(){
21         return "name= "+this.getName();
22     }
23 }
24 
25 public class Test {
26     
27     public static void main(String[] args) throws Exception {
28         // TODO Auto-generated method stub
29         Class<?> c=null;
30         c=Class.forName("yxy.Person");
31         Constructor<?>[] cons=null;
32         cons=c.getConstructors();
33         Person person=null;
34         //输出所有公有构造函数,私有的是不能得到的
35         for(Constructor<?> con:cons){
36             System.out.println(con);
37         }
38         person=(Person) cons[1].newInstance("crane");
39         System.out.println(person);
40     }
41 }

运行结果:

public yxy.Person()
public yxy.Person(java.lang.String)
name= crane

 呃,震惊了,私有属性和方法的也可以通过反射被看到:http://www.pengtaoblog.cn/article.asp?id=721

呃,原来这个人写的都有啦:http://www.cnblogs.com/octobershiner/archive/2012/03/18/2404751.html  这是个好文章

还有个好文章哇:候捷谈Java反射机制http://www.cppblog.com/javenstudio/articles/24640.html

禁止反射http://bbs.csdn.net/topics/390472034?page=1#post-394609835

反射的应用场景:http://bbs.itheima.com/thread-88932-1-1.html

第一讲    反射的应用场景
一、概述
反射技术:
        Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
        简单一句话:反射技术可以对类进行解剖。
 
二、应用场景
        一个已经可以使用的应用程序,因为程序已经做好可以运行使用,不能再进行代码的加入了。而当后期我们新的功能加入程序时,该怎么做呢?就如我们的电脑一样,后期我们可能会鼠标、键盘等,所以电脑给我们预留了usb接口,只要符合这个接口规则的设备,电脑就可以通过加载驱动等操作来使用。
        那这个程序能用了,如何使用后期出现的功能类呢?
        常用的作法,会提供一个配置文件,来供以后实现此程序的类来扩展功能。对外提供配置文件,让后期出现的子类直接将类名字配置到配置文件中即可。该应用程序直接读取配置文件中的内容。并查找和给定名称相同的类文件。进行如下操作:
        1)加载这个类。
        2)创建该类的对象。
        3)调用该类中的内容。
       应用程序使用的类不确定时,可以通过提供配置文件,让使用者将具体的子类存储到配置文件中。然后该程序通过反射技术,对指定的类进行内容的获取。
        好处:反射技术大大提高了程序的扩展性。

更加详细的:http://blog.csdn.net/benjaminzhang666/article/details/9408611

crane:SSH框架中都用到了反射机制(读配置文件获得类名,然后进行反射操作)

《Effective Java》中文版第2版第53条中有说到反射机制的注意事项,

反射是在运行时执行的,丧失了编译时类型检查的好处,包括异常检查,如果程序反射的调用不存在的方法,在运行时会失败,除非采取了特别的预防措施。

详情参看那本书

原文地址:https://www.cnblogs.com/crane-practice/p/3671952.html