博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java反射机制
阅读量:5767 次
发布时间:2019-06-18

本文共 5117 字,大约阅读时间需要 17 分钟。

谈到Spring时大家都会想到它的核心原理是IOC/DI,其实Spring实现IOC/DI的背后依靠的是Java反射机制。不仅Spring使用反射机制,Hibernate的ORM框架也是使用反射机制实现的,AOP动态代理也是大量使用反射实现的,所以Java反射机制其实已经被大量应用在我们的程序中,只是平时我们做业务应用开发时直接使用Java反射的机会比较少,因为我们不需要重复发明轮子,大部分应用的开发都会使用一些像Spring这样成熟的框架,开发人员只需要提供框架配置文件即可。框架让我们可以更专注业务逻辑开发,但对于提高架构设计能力,我们还是需要掌握框架背后的实现,说不定将来我们需要开发自己的框架或者定制开源框架。

Reflection,这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

反射被大量使用肯定有其优点,从上面的定义可以看出反射的优点就是动态灵活,一切都是在运行时期根据具体情况(配置)决定创建哪种对象、调用哪个方法等。这种灵活性可以方便我们设计解耦,这也是Spring做得最好的事情之一,所以我们可以很方便的替换某些class文件而不需要重新编译相关类。事物都是两面的,反射当然也有缺点,对于编译期能确定的事情,编译器可以或多或少做些优化,而运行期就像解释执行一样,编译器一般没法进行优化,所以使用反射性能要打点折扣;另外反射破坏类的封装性,通过反射我们可以访问类的任何成员,包括private成员,这违反了面向对象设计原则。

java.lang.Class类:反射中最常出现的类,它跟其它JAVA类没什么两样只是名字恰巧叫Class,都是继承于Object类,其实它就是JAVA类的抽象,用来描述类的元数据,比如每个类都有类名、装载器、哈希等,这些都是Class类的属性。Class没有public的构造函数,当Java虚拟机载入一个类的时候,它就会自动创建一个Class类的实例来表示这个类,比如java.lang.String,我们可以通过String.class来获取对应的Class类实例;或者我们也可以通过Class.forName("类全名")来获取一个Class对象。

反射常用的一些方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Class c = Class.forName(
"className"
); 
//className必须为全名 
Object obj = c.newInstance();
//创建实例 
  
Constructor getConstructor(Class[] params);
//根据指定参数获得public构造函数
 
Constructor[] getConstructors();
//获得所有public构造函数
 
Method getMethod(String name, Class[] params); 
//根据方法名,参数类型获得public方法
 
Method[] getMethods();
//获得所有的public方法
 
Field getField(String name);
//根据变量名得到相应的public变量
 
Field[] getFields();
//获得类中所以public的变量

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package 
com.stevex.app.forkjoin;
 
import 
java.math.BigDecimal;
 
public 
class 
Account 
implements 
java.io.Serializable{
    
public 
static 
final 
long 
serialVersionUID = -6928173218630110362L;
    
private 
String id;
    
private 
String clientId;
    
private 
BigDecimal balance;
 
    
public 
Account(){
        
//default constructor
    
}
     
    
public 
Account(String id, String clientId) {
        
this
.id = id;
        
this
.clientId = clientId;
        
balance = BigDecimal.ZERO;
    
}
 
    
public 
synchronized 
void 
withdraw(String clientId, BigDecimal amount){
        
validateClient(clientId);
         
        
if
(amount.compareTo(balance) < 
1
){
            
balance.subtract(amount);
        
}
        
else
{
            
throw 
new 
RuntimeException(
"余额不足"
);
        
}
    
}
     
    
private 
void 
validateClient(String clientId) {
        
if
(! 
this
.clientId.equals(clientId)){
            
throw 
new 
RuntimeException(
"非法客户"
);
        
}
    
}
 
    
public 
synchronized 
void 
deposit(BigDecimal amount){
        
if
(amount.compareTo(BigDecimal.ZERO) == 
1
){
            
balance.add(amount);
        
}
        
else
{
            
throw 
new 
RuntimeException(
"不允许透支"
);
        
}
    
}
     
    
public 
String getClientId() {
        
return 
clientId;
    
}
     
    
public 
void 
setClientId(String clientId) {
        
this
.clientId = clientId;
    
}
     
    
public 
String getId() {
        
return 
id;
    
}
     
    
public 
void 
setId(String id) {
        
this
.id = id;
    
}
}
 
 
package 
com.stevex.app.forkjoin;
 
import 
java.lang.reflect.Constructor;
import 
java.lang.reflect.Field;
import 
java.lang.reflect.Method;
 
public 
class 
ReflectionTest {
 
    
public 
static 
void 
main(String[] args) 
throws 
ClassNotFoundException,
            
InstantiationException, IllegalAccessException {
        
Class c = Class.forName(
"com.stevex.app.forkjoin.Account"
);
        
Account account = (Account) c.newInstance();
 
        
Constructor[] cons = c.getConstructors();
        
Method[] methods = c.getMethods();
        
Field[] fields = c.getFields();
         
        
for
(Constructor con : cons){
            
System.out.println(con);
        
}
         
        
for
(Method m : methods){
            
System.out.println(m);
        
}
         
        
for
(Field f : fields){
            
System.out.println(f);
        
}
    
}
 
}

发现输出结果蛮有趣的,就连父类Object中定义的public成员都输出了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public 
com.stevex.app.forkjoin.Account()
public 
com.stevex.app.forkjoin.Account(java.lang.
String
,java.lang.
String
)
public 
java.lang.
String 
com.stevex.app.forkjoin.Account.getId()
public 
synchronized 
void 
com.stevex.app.forkjoin.Account.withdraw(java.lang.
String
,java.math.BigDecimal)
public 
synchronized 
void 
com.stevex.app.forkjoin.Account.deposit(java.math.BigDecimal)
public 
java.lang.
String 
com.stevex.app.forkjoin.Account.getClientId()
public 
void 
com.stevex.app.forkjoin.Account.setClientId(java.lang.
String
)
public 
void 
com.stevex.app.forkjoin.Account.setId(java.lang.
String
)
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 
final 
native 
void 
java.lang.
Object
.wait(long) 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()
public 
static 
final 
long com.stevex.app.forkjoin.Account.serialVersionUID
     本文转自sarchitect 51CTO博客,原文链接:http://blog.51cto.com/stevex/1577333
,如需转载请自行联系原作者
你可能感兴趣的文章
haproxy mysql实例配置
查看>>
强化学习的未来— 第一部分
查看>>
TableStore:用户画像数据的存储和查询利器
查看>>
2019 DockerCon 大会即将召开,快来制定您的专属议程吧!
查看>>
15分钟构建超低成本数据大屏:DataV + DLA
查看>>
jSearch(聚搜) 1.0.0 终于来了
查看>>
盘点2018云计算市场,变化大于需求?
查看>>
极光推送(一)集成
查看>>
MySQL 8.0 压缩包版安装方法
查看>>
@Transient注解输出空间位置属性
查看>>
Ansible-playbook 条件判断when、pause(学习笔记二十三)
查看>>
5种你未必知道的JavaScript和CSS交互的方法(转发)
查看>>
线程进程间通信机制
查看>>
galera mysql 多主复制启动顺序及命令
查看>>
JS prototype 属性
查看>>
中位数性质——数列各个数到中位数的距离和最小
查看>>
WebApp之Meta标签
查看>>
添加Java文档注释
查看>>
Python3批量爬取网页图片
查看>>
iphone-common-codes-ccteam源代码 CCEncoding.m
查看>>