JavaSE:反射
概述关于java.lang.Class类的理解
通过反射创建运行时类的对象对比Class类的实例化使用ClassLoader加载配置文件使用反射获取运行时类的完整结构属性方法获取带泛型的父类以及其泛型获取运行时类的接口、所在包、注解
动态代理动态代理代码示例:
概述
Reflection(反射):是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
加载完类之后,在对内存的方法区中就产生了一个class类型的对象(一个类只有一个class对象),这个对象就包含了完整的类的结构信息。外面可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。
动态语言:
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。
主要动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang
静态语言:
与动态语言相对的,运行时结构不可变的语言就是静态语言。如:Java、C、C++。
Java不是动态语言,但Java可以称为“准动态语言”。即Java由一定的动态性,外面可以利用反射机制、字节码操作获得类似动态语言的特性。
反射机制提供的功能:
在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象在运行时判断任意一个类所具有的成员变量和方法在运行时获取泛型信息在运行时调用任意一个对象的成员变量和方法在运行时处理注解生成动态代理
关于java.lang.Class类的理解
类的加载过程:
程序在经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)接着使用java.exe命令对某个字节码文件进行解释运行,像用于将某个字节码文件加载到内存中,此过程就称为类的加载。加载到内存中的类,外面就i称为运行时类,就作为Class的一个实例。换句话说,Class的实例对应着一个运行时类。加载到内存中的运行时类,会缓存一定的时间。在此时间内,我们可以通过不同的方式来获取此运行时类。
类的加载过程:
通过反射创建运行时类的对象
对比
@Test
public void test1() throws Exception
{
Person person
= new Person("张三", 21);
System
.out
.println(person
);
person
.age
= 18;
System
.out
.println(person
);
person
.show();
System
.out
.println("******************* 反射 *******************");
Class
<Person> p
= Person
.class;
Constructor
<Person> constructor
= p
.getConstructor(String
.class, int.class);
Person person1
= constructor
.newInstance("李四", 22);
System
.out
.println(person1
);
Field age
= p
.getDeclaredField("age");
age
.set(person1
,18);
System
.out
.println(person1
);
Method show
= p
.getDeclaredMethod("show");
show
.invoke(person1
);
System
.out
.println("******************* 反射获取私有结构 *******************");
Class
<Person> p2
= Person
.class;
Constructor
<Person> constructor1
= p2
.getDeclaredConstructor(String
.class);
constructor1
.setAccessible(true);
Person person2
= constructor1
.newInstance("王五");
System
.out
.println(person2
);
Field name
= p2
.getDeclaredField("name");
name
.setAccessible(true);
name
.set(person2
,"赵六");
System
.out
.println(person2
);
Method getNation
= p2
.getDeclaredMethod("getNation", String
.class);
getNation
.setAccessible(true);
String str
= (String
) getNation
.invoke(person2
, "中国");
System
.out
.println(str
);
}
运行结果
Class类的实例化
@Test
public void test2() throws Exception
{
Class
clazz = Person
.class;
Person p
= new Person("Tom", 28);
Class
clazz2 = p
.getClass();
Class
clazz3 = Class
.forName("Person");
System
.out
.println( clazz
== clazz2
);
System
.out
.println(clazz
== clazz3
);
ClassLoader loader
= p
.getClass().getClassLoader();
Class
clazz4 = loader
.loadClass("Person");
System
.out
.println(clazz
== clazz4
);
}
使用ClassLoader加载配置文件
@Test
public void test3() throws Exception
{
Properties pro
= new Properties();
FileInputStream fis
= new FileInputStream("jdbc.properties");
pro
.load(fis
);
String username
= pro
.getProperty("username");
String password
= pro
.getProperty("password");
System
.out
.println("用户名为:" + username
+ ",密码为:" + password
);
}
使用反射获取运行时类的完整结构
属性
@Test
public void test(){
Class
clazz = Person
.class;
Field
[] fields
= clazz
.getFields();
for(Field f
:fields
){
System
.out
.println(f
);
}
System
.out
.println("*********************************************************");
Field
[] field
= clazz
.getDeclaredFields();
for(Field f
:field
){
int modifier
= f
.getModifiers();
System
.out
.print(Modifier
.toString(modifier
) + "\t");
Class
<?> type
= f
.getType();
System
.out
.print(type
.getName() + "\t");
String name
= f
.getName();
System
.out
.print(name
);
System
.out
.println();
}
}
方法
@Test
public void test2(){
Class
clazz = Person
.class;
Method
[] methods
= clazz
.getDeclaredMethods();
for (Method method
:methods
){
int modifiers
= method
.getModifiers();
System
.out
.print(Modifier
.toString(modifiers
) + "\t");
Class
<?> type
= method
.getReturnType();
System
.out
.print(type
.getName() + "\t");
String name
= method
.getName();
System
.out
.print(name
+ "\t");
System
.out
.print("(");
Class
<?>[] parameterTypes
= method
.getParameterTypes();
if (parameterTypes
.length
> 0){
for (int i
= 0; i
< parameterTypes
.length
; i
++) {
if (i
== parameterTypes
.length
- 1){
System
.out
.print(parameterTypes
[i
].getName() + "\targs_" + i
);
break;
}
System
.out
.print(parameterTypes
[i
].getName() + "\targs_" + i
+ ",");
}
}
System
.out
.print(")");
Class
<?>[] exceptionTypes
= method
.getExceptionTypes();
if (exceptionTypes
.length
> 0){
System
.out
.print("\tthrows\t");
for (int i
= 0; i
< exceptionTypes
.length
; i
++) {
if (i
== exceptionTypes
.length
- 1){
System
.out
.print(exceptionTypes
[i
].getName());
break;
}
System
.out
.print(exceptionTypes
[i
].getName() + ",");
}
}
System
.out
.println("{}");
}
}
构造器同上。
获取带泛型的父类以及其泛型
@Test
public void test3(){
Class
clazz = Person
.class;
Type type
= clazz
.getGenericSuperclass();
ParameterizedType paramType
= (ParameterizedType
) type
;
Type
[] args
= paramType
.getActualTypeArguments();
for(Type arg
:args
){
System
.out
.println(arg
.getTypeName());
}
}
获取运行时类的接口、所在包、注解
@Test
public void test4(){
Class
clazz = Person
.class;
Class
[] interfaces
= clazz
.getInterfaces();
for (Class
interfacess:interfaces
){
System
.out
.println(interfacess
);
}
Package aPackage
= clazz
.getPackage();
System
.out
.println(aPackage
);
Annotation
[] annotations
= clazz
.getAnnotations();
for (Annotation anno
:annotations
){
System
.out
.println(anno
);
}
}
动态代理
代理设计模式的原理:
使用一个代理将对象包装起来,然后用此代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
静态代理:特征是代理类和目标类对象的类都是在编译期间确定下来的,不利于程序的扩展。同时,每个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。最好可以通过一个代理类完成全部的代理功能。
动态代理是指客户通过代理类来调用其他对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
动态代理相比静态代理的优点:
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更灵活和统一的处理众多的方法。
动态代理代码示例:
public class ProxyTest {
public static void main(String
[] args
) {
ANTAClothFactory a
= new ANTAClothFactory();
clothFactory instance
= (clothFactory
) ProxyFactory
.getInstance(a
);
instance
.productCloth();
String name
= instance
.getName("ANTA");
System
.out
.println(name
);
}
}
interface clothFactory{
void productCloth();
String
getName(String name
);
}
class ANTAClothFactory implements clothFactory{
@Override
public void productCloth() {
System
.out
.println("ANTA生产了一批衣服");
}
@Override
public String
getName(String name
) {
return name
;
}
}
class ProxyFactory{
public static Object
getInstance(Object obj
){
MyInvocationHandler handler
= new MyInvocationHandler();
handler
.bind(obj
);
ClassLoader loader
= obj
.getClass().getClassLoader();
return Proxy
.newProxyInstance(loader
, obj
.getClass().getInterfaces(),handler
);
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj
;
public void bind(Object obj
){
this.obj
= obj
;
}
@Override
public Object
invoke(Object proxy
, Method method
, Object
[] args
) throws Throwable
{
System
.out
.println("动态代理");
return method
.invoke(obj
,args
);
}
}
运行结果