Java语言之反射机制
白羽 2018-07-09 来源 :网络 阅读 582 评论 0

摘要:本文将带你了解Java语言之反射机制,希望本文对大家学JAVA有所帮助。

   

 

Java反射机制(带应用)

1、Java的反射机制:

 

       Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

      Java反射机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。

       但是Java有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

************************************************************************************************************************

以上是百度百科中对Java反射机制的解释。

 

 

2、Java反射机制的功能:

 

(1)在运行时判断任意一个对象所属的类;

(2)在运行时构造任意一个类的对象;

(3)在运行时判断任意一个类所具有的成员变量和方法;

(4)在运行时调用任意一个对象的方法;生成动态代理。

 

 

 

3、与反射相关的类有:

 

Class:表示类、Field:表示成员变量、 Method:表示方法、Constructor:表示构造器。

 

 

 

4、获取Class类的三种基本方式:

 

(1)通过     类名称.class,对基本类型也支持;

               Class c = int.class;

           Class c = int[ ].class;

           Class c = String.class

(2)通过    对象.getClass( )方法

         Class c = obj.getClass(  );

(3) Class.forName( )  通过类名称加载类,这种方法只要有类名称就可以得到Class;

         Class c = Class.forName(“cn.ywq.Demo”);

 

示例:通过反射来创建一个对象,利用.newInstance( )方法来实现。

[java] view plain copy
1. public class Demo1 {  
2.     @Test  
3.     public void fun1() throws Exception {  
4.         String className = "cn.ywq.User";  
5.         Class clazz = Class.forName(className);   
6.         User user = (User)clazz.newInstance();  
7.         System.out.println(user);  
8.     }  
9. }  
10.   
11. class User {  
12.     private String username;  
13.     private String password;  
14.   
15.     public String getUsername() {  
16.         return username;  
17.     }  
18.   
19.     public void setUsername(String username) {  
20.         this.username = username;  
21.     }  
22.   
23.     public String getPassword() {  
24.         return password;  
25.     }  
26.   
27.     public void setPassword(String password) {  
28.         this.password = password;  
29.     }  
30.   
31.     @Override  
32.     public String toString() {  
33.         return "User [username=" + username + ", password=" + password + "]";  
34.     }  
35. }  
 
5、Field类的使用
Field表示类的成员变量,可以是实例变量,也可以是静态变量。
 
(1)获取Field对象,
获取Field对象需要使用Class对象,下面是Class类的API:
Field getField(String name):通过名字获取公有成员变量的反射对象,包含父类中声明的公有成员变量;
Field[ ] getFields():获取所有公有成员变量反射对象,包含父类中声明的公有成员变量;
Field getDeclaredField(String name):通过名字获取本类中某个成员变量,包含本类的private成员变量,但父类中声明的任何成员变量都不包含;
Field[ ] getDeclaredFields():获取本类中声明的所有成员变量,包含private成员变量,但不包含父类中声明的任何成员变量;
 
(2)Field类的常用方法
String getName():获取成员变量名;
Class getDeclaringClass():获取成员变量的类型;
Class getType():获取当前成员变量的类型;
Object get(Object obj):获取obj对象的成员变量的值;
void set(Object obj, Object value):设置obj对象的成员变量值为value;
 
示例:通过Field读写成员
User.java
[java] view plain copy
1. public class User {  
2.     public String username;  
3.     public String password;  
4.   
5.     public User() {  
6.     }  
7.   
8.     public User(String username, String password) {  
9.         this.username = username;  
10.         this.password = password;  
11.     }  
12.   
13.     public String getUsername() {  
14.         return username;  
15.     }  
16.   
17.     public void setUsername(String username) {  
18.         this.username = username;  
19.     }  
20.   
21.     public String getPassword() {  
22.         return password;  
23.     }  
24.   
25.     public void setPassword(String password) {  
26.         this.password = password;  
27.     }  
28.   
29.     @Override  
30.     public String toString() {  
31.         return "User [username=" + username + ", password=" + password + "]";  
32.     }  
33. }  
Demo1.java
[java] view plain copy
1. public class Demo1 {  
2.     @Test  
3.     public void fun1() throws Exception {  
4.         String className = "cn.itcast.User";  
5.         Class clazz = Class.forName(className);  
6.         User user = new User("zhangSan", "123");  
7.           
8.         Field field1 = clazz.getField("username");   
9.         Field field2 = clazz.getField("password") ;  
10.           
11.         String username = (String)field1.get(user);   
12.         String password = (String)field2.get(user);   
13.           
14.         System.out.println(username + ", " + password);  
15.           
16.         field1.set(user, "liSi");   
17.         field2.set(user, "456");   
18.           
19.         System.out.println(user);  
20.     }  
21. }  
 
 
 
 
6、Constructor类的使用
 
 Constructor表示一个类的构造器。即构造器的反射对象!
 
(1)获取Constructor对象
获取Construcator对象需要使用Class对象,下面API来自Class类:
Constructor getConstructor(Class… parameterTypes):通过指定的参数类型获取公有构造器反射对象;
Constructor[ ] getConstructors(  ):获取所有公有构造器对象;
Constructor getDeclaredConstructor(Class… parameterTypes):通过指定参数类型获取构造器反射对象。可以是私有构造器对象;
Constructor[ ] getDeclaredConstructors():获取所有构造器对象。包含私有构造器;
 
(2)Construcator类常用方法
  String getName():获取构造器名;
  Class getDeclaringClass():获取构造器所属的类型;
  Class[ ] getParameterTypes():获取构造器的所有参数的类型;
  Class[ ] getExceptionTypes():获取构造器上声明的所有异常类型;
  newInstance(Object… initargs):通过构造器反射对象调用构造器。
 
示例:通过Construcator创建对象 
User.java
[java] view plain copy
1. public class User {  
2.     private String username;  
3.     private String password;  
4.   
5.     public User() {  
6.     }  
7.   
8.     public User(String username, String password) {  
9.         this.username = username;  
10.         this.password = password;  
11.     }  
12.   
13.     public String getUsername() {  
14.         return username;  
15.     }  
16.   
17.     public void setUsername(String username) {  
18.         this.username = username;  
19.     }  
20.   
21.     public String getPassword() {  
22.         return password;  
23.     }  
24.   
25.     public void setPassword(String password) {  
26.         this.password = password;  
27.     }  
28.   
29.     @Override  
30.     public String toString() {  
31.         return "User [username=" + username + ", password=" + password + "]";  
32.     }  
33. }  
 
Demo1.java
[java] view plain copy
1. public class Demo1 {  
2.     @Test  
3.     public void fun1() throws Exception {  
4.         String className = "cn.itcast.User";  
5.         Class clazz = Class.forName(className);  
6.         Constructor c = clazz.getConstructor(String.class, String.class);  
7.         User user = (User)c.newInstance("zhangSan", "123");  
8.         System.out.println(user);  
9.     }  
10. }  
 
 
7、Method类的使用 
 
(1)获取Method
获取Method需要通过Class对象,下面是Class类的API:
  Method getMethod(String name, Class… parameterTypes):通过方法名和方法参数类型获取方法反射对象,包含父类中声明的公有方法,但不包含所有私有方法;
  Method[ ]   getMethods():获取所有公有方法,包含父类中的公有方法,但不包含任何私有方法;
  Method getDeclaredMethod(String name, Class… parameterTypes):通过方法名和方法参数类型获取本类中声明的方法的反射对象,包含本类中的私有方法,但不包含父类中的任何方法;
 Method[  ] getDeclaredMethods( ):获取本类中所有方法,包含本类中的私有方法,但不包含父类中的任何方法。
 
(2)Method常用方法
  String getName( ):获取方法名;
  Class getDeclaringClass( ):获取方法所属的类型;
  Class[ ] getParameterTypes( ):获取方法的所有参数的类型;
  Class[ ] getExceptionTypes( ):获取方法上声明的所有异常类型;
  Class getReturnType( ):获取方法的返回值类型;
  Object invoke(Object obj, Object… args):通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,如果当前方法是static方法,那么可以给obj传递null。args表示是方法的参数;
 
示例:通过Method调用方法
[java] view plain copy
1. public class Demo1 {  
2.     @Test  
3.     public void fun1() throws Exception {  
4.         String className = "cn.ywq.User";  
5.         Class clazz = Class.forName(className);  
6.         Constructor c = clazz.getConstructor(String.class, String.class);  
7.         User user = (User)c.newInstance("zhangSan", "123");  
8.           
9.         Method method = clazz.getMethod("toString");  
10.         String result = (String)method.invoke(user);  
11.         System.out.println(result);  
12.     }  
13. }

 

 

 

8、AccessibleObject的使用

 

AccessibleObject类是Constructor、Method、Field三个类的父类。AccessibleObject最为重要的方法如下:

boolean isAccessible( ):判断当前成员是否可访问;

voidsetAccessible(boolean flag):设置当前成员是否可访问。

当Constructor、Method、Field为私有时,如果我们想反射操作,那么就必须先调用反射对象的setAccessible(true)方法,然后才能操作。

User.java

[java] view plain copy
1. public class User {  
2.     private String username;  
3.     private String password;  
4.   
5.     public User() {  
6.     }  
7.   
8.     public User(String username, String password) {  
9.         this.username = username;  
10.         this.password = password;  
11.     }  
12.   
13.     public String getUsername() {  
14.         return username;  
15.     }  
16.   
17.     public void setUsername(String username) {  
18.         this.username = username;  
19.     }  
20.   
21.     public String getPassword() {  
22.         return password;  
23.     }  
24.   
25.     public void setPassword(String password) {  
26.         this.password = password;  
27.     }  
28.   
29.     @Override  
30.     public String toString() {  
31.         return "User [username=" + username + ", password=" + password + "]";  
32.     }  
33. }  
注意,User类的username和password成员变量为private的,这时再通过Field来反射操作这两个成员变量就必须先通过setAccessible(true)设置后才行。
[java] view plain copy
1. public class Demo1 {  
2.     @Test  
3.     public void fun1() throws Exception {  
4.         String className = "cn.ywq.User";  
5.         Class clazz = Class.forName(className);  
6.         User user = new User("zhangSan", "123");  
7.           
8.         Field field1 = clazz.getDeclaredField("username");  
9.         Field field2 = clazz.getDeclaredField("password");  
10.           
11.         field1.setAccessible(true);  
12.         field2.setAccessible(true);  
13.           
14.         String username = (String)field1.get(user);  
15.         String password = (String)field2.get(user);  
16.           
17.         System.out.println(username + ", " + password);  
18.           
19.         field1.set(user, "liSi");  
20.         field2.set(user, "456");  
21.           
22.         System.out.println(user);  
23.     }  
24. }

 


 

9、Java反射机制在工厂方法模式中的使用:

 

       工厂方法模式模式主要的作用就是创建一个对象,它是new一个对象的替代品。在所有需要生成对象的地方都可以使用。

       工厂方法模式利用Java的反射机制来得到Class类,利用newInstance(  )方法来创建一个对象。

通用类图如下所示:

 Java语言之反射机制

通用源代码:

[java] view plain copy
1. //抽象产品类  
2. public abstract class Product {      
3.     //产品类的公共方法  
4.     public void method1(){  
5.             //业务逻辑处理  
6.     }    
7.     //抽象方法  
8.     public abstract void method2();      
9. }  
10.   
11. //多个具体产品类  
12. public class ConcreteProduct1 extends Product {  
13.     public void method2() {  
14.             //业务逻辑处理  
15.     }  
16. }  
17. public class ConcreteProduct2 extends Product {  
18.     public void method2() {  
19.             //业务逻辑处理  
20.     }  
21. }  
22.   
23. //抽象工厂类  
24. public abstract class Creator {      
25.     /* 
26.      * 创建一个产品对象,其输入参数类型可以自行设置 
27.      * 通常为String、Enum、Class等,当然也可以为空 
28.      */          
29.     public abstract <T extends Product> T create Product(Class<T> c);  
30. }  
31.   
32. //具体工厂类  
33. public class ConcreteCreator extends Creator {       
34.     public <T extends Product> T create Product(Class<T> c){  
35.             Product product=null;  
36.             try {  
37.                    product = (Product)Class.forName(c.get Name()).new Instance();  
38.             } catch (Exception e) {  
39.                    //异常处理  
40.             }  
41.             return (T)product;           
42.     }  
43. }  
测试代码如下:
[java] view plain copy
1. public class Client {  
2.     public static void main(String[] args) {  
3.             Creator creator = new ConcreteCreator();  
4.             Product product = creator.createProduct(ConcreteProduct1.class);  
5.             /* 
6.              * 继续业务处理 
7.              */  
8.     }  
9. }

 

可以看到,工厂方法模式中,在具体的工厂中使用了反射机制来创建了一个product的对象。

 

 



以上就介绍了JAVA的相关知识,希望对JAVA有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言JAVA频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程