四、反射
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Class类与java.lang.reflect类库一起对反射的概念进行了支持,该类库包含了Field、Method、Constructor等类,每个类都实现了Member接口,该接口代表一个特定的成员(变量,方法或者构造器)。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class Test
{
public int i;
float j;
public Testa(){}
private Testa(String str){}
public void fun(){}
}
public class ReflectTest
{
//打印数组的方法
public static void print(String name, Object[] array)
{
System.out.println("-----" + name + "------");
for(Object obj : array)
{
System.out.println(obj);
}
System.out.println("---------------------------");
}
public static void main(String[] args)
{
Class<Test> c = Test.class;
//获得所有声明的方法、变量和构造器
Method[] declaredMethods = c.getDeclaredMethods();
Field[] declaredFields = c.getDeclaredFields();
Constructor[] declareConstructors = c.getDeclaredConstructors();
//获得所有public的方法、变量和构造器
Method[] publicMethods = c.getMethods();
Field[] publicFields = c.getFields();
Constructor[] publicConstructors = c.getConstructors();
print("declared methods", declaredMethods);
print("declared fields", declaredFields);
print("declared constructors", declareConstructors);
print("public methods", publicMethods);
print("public fields", publicFields);
print("public constructors", publicConstructors);
}
}
输出
-----declared methods------
public static void Test.main(java.lang.String[])
---------------------------
-----declared fields------
---------------------------
-----declared constructors------
public Test()
---------------------------
-----public methods------
public static void Test.main(java.lang.String[])
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
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 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 fields------
---------------------------
-----public constructors------
public Test()
---------------------------
五、动态代理
代理是基本的设计模式之一,它是为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。而Java的动态代理比代理的思想更向前迈进了一步,因为它可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface AbstractSubject
{
public void fun1();
public void fun2();
}
class RealSubject implements AbstractSubject
{
public void fun1()
{
System.out.println("fun1 invoked!");
}
public void fun2()
{
System.out.println("fun2 invoked!");
}
}
/**
* 代理的调用处理器
*/
class DynamicProxyHandler implements InvocationHandler
{
private AbstractSubject proxied;
//传入需要被代理的对象
public DynamicProxyHandler(AbstractSubject proxied)
{
this.proxied = proxied;
}
//将方法的调用重定向到被代理的对象,同时增加额外操作
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
System.out.print("From Proxy : ");
return method.invoke(proxied, args);
}
}
public class DynamicProxy
{
public static void main(String[] args)
{
RealSubject subject = new RealSubject();
DynamicProxyHandler proxyHandler = new DynamicProxyHandler(subject);
//使用Proxy类的newProxyinstance方法生成代理对象
//需要传入被代理对象的类加载器,实现的接口和对应的调用处理器
AbstractSubject proxy = (AbstractSubject) Proxy.newProxyInstance(subject
.getClass().getClassLoader(), subject.getClass().getInterfaces(),
proxyHandler);
//直接调用
subject.fun1();
subject.fun2();
//代理调用
proxy.fun1();
proxy.fun2();
}
}
输出
fun1 invoked!
fun2 invoked!
From Proxy : fun1 invoked!
From Proxy : fun2 invoked!
六、空对象
在Java中,当使用内置的null表示缺少对象或者空对象时,在每次使用引用的时候都必须测试其是否为null,否则有可能抛出NullPointerException。这个时候引入“空对象”的思想将会很有用,“空对象”代表这样一些类和对象,它们并无意义,但是能代替null来表示空的对象,从而避免使用null。有了“空对象”,我们很很多情况下能把它们当作正常类来处理,只是使用这些“空对象”时会产生代表“空”的效果。
import java.util.ArrayList;
/*
* 代表“空”的标志接口
*/
interface Null{}
/*
* 代表一个具体的人
*/
class Person
{
public final String name;
public final String gender;
public Person(String name, String gender)
{
this.name = name;
this.gender = gender;
}
public String toString()
{
return "name:" + name + ", gender:" + gender;
}
}
/*
* 代表“没有人”的空对象
* 使用单例模式,因为NullPerson一一致的,是通用的
*/
class NullPerson extends Person implements Null
{
private static NullPerson nullPerson = new NullPerson();
private NullPerson()
{
super("NONE", "NONE");
}
public static NullPerson getNullPerson()
{
return nullPerson;
}
}
/*
* 代表职位的类,包含职位名称和对应的人
*/
class Position
{
private String position;
private Person person;
public Position(String position, Person person)
{
this.position = position;
this.person = person;
}
public String toString()
{
return position + " --- " + person;
}
}
public class NullTest
{
public static void main(String[] args)
{
//代表某公司职位信息的List
ArrayList<Position> companyPosition = new ArrayList<Position>();
//往List中加入职位,当某个职位空缺时,该职位的人用“空对象”表示
companyPosition.add(new Position("CEO", new Person("Ben", "male")));
companyPosition.add(new Position("Software Engineer", new Person("George", "male")));
companyPosition.add(new Position("Hardware Engineer", NullPerson.getNullPerson()));
companyPosition.add(new Position("Dedigner", new Person("Tracy", "female")));
//可以把所有元素当作正常的Person处理而不用担心因为null带来的异常或类型检测
for(Position p : companyPosition)
{
System.out.println(p);
}
}
}
输出:
CEO --- name:Ben, gender:male
Software Engineer --- name:George, gender:male
Hardware Engineer --- name:NONE, gender:NONE
Dedigner --- name:Tracy, gender:female