背景
继续查缺补漏。
1.为使用类而准备的工作
当使用“.class”来创建对Class对象的引用时,不会自动地初始化该Class对象。
为了使用类而做的准备工作步骤如下:
(1)加载。由类加载器执行。该步骤将查找字节码(通常在classpath指定的路径中查找,但这并非是必须的),
并从这些字节码中创建一个Class对象。
(2)链接。在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类创建
的对其他类的所有引用。
(3)初始化。如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。
初始化被延迟到了对静态方法(构建器隐式地是静态的)或者非常数静态域(一个staic域不是final的)进行首
次引用时才被执行。
2.泛化的Class引用
为了创建一个Class引用,它被限定为某种类型,或该类型的任何子类型,将通配符与extends相结合,创建一
个范围:
Class<?> integer=int.class;
Class<? extends Number> bounded=int.class;
bounded=double.class;
bounded=Number.class;
通配符“?”表示“任何事物”。向class引用添加泛型语法是为了提供编译期类型检查。
3.newInstance
如果是超类,必须声明超类引用是“某个类,它是FancyToy超类”。newInstance()的返回值是Object类型。
Class<FancyToy> ftClass=FancyToy.class;
FancyToy fancyToy=ftClass.newInstance();
Class<? super FancyToy> up=ftClass.getSuperclass();
Object obj=up.newInstance();
4.cast
cast()方法接受参数对象,并将其转型为Class引用的类型
Class<House> houseType=House.class;
House h=houseType.cast(b);
5.isAssignableFrom
用来执行运行时的检查,可以检验对象的继承结构。
Class<?> baseType;
Class<?> superClass=type.getSuperClass();
baseType.isAssignableFrom(superClass);
6.注册工厂
public interface Factory<T> {
T create();
}
package c14;
import java.util.*;
import java.lang.reflect.*;
class Part{
public String toString(){
return getClass().getSimpleName();
}
static List<Factory<? extends Part>> partFactories=new ArrayList<Factory<? extends Part>>();
static{
partFactories.add(new FuelFilter.Factory());
partFactories.add(new AirFilter.Factory());
partFactories.add(new CabinAirFilter.Factory());
partFactories.add(new OilFilter.Factory());
partFactories.add(new FanBelt.Factory());
partFactories.add(new PowerSteeringBelt.Factory());
partFactories.add(new GeneratorBelt.Factory());
}
private static Random rand=new Random(47);
public static Part createRandom(){
int n=rand.nextInt(partFactories.size());
return partFactories.get(n).create();
}
}
class Filter extends Part{}
class FuelFilter extends Filter{
public static class Factory implements c14.Factory<FuelFilter>{
public FuelFilter create(){ return new FuelFilter();}
}
}
class AirFilter extends Filter{
public static class Factory implements c14.Factory<AirFilter>{
public AirFilter create(){ return new AirFilter();}
}
}
class CabinAirFilter extends Filter{
public static class Factory implements c14.Factory<CabinAirFilter>{
public CabinAirFilter create(){ return new CabinAirFilter();}
}
}
class OilFilter extends Filter{
public static class Factory implements c14.Factory<OilFilter>{
public OilFilter create(){ return new OilFilter();}
}
}
class Belt extends Part{}
class FanBelt extends Belt{
public static class Factory implements c14.Factory<FanBelt>{
public FanBelt create(){ return new FanBelt();}
}
}
class GeneratorBelt extends Belt{
public static class Factory implements c14.Factory<GeneratorBelt>{
public GeneratorBelt create(){ return new GeneratorBelt();}
}
}
class PowerSteeringBelt extends Belt{
public static class Factory implements c14.Factory<PowerSteeringBelt>{
public PowerSteeringBelt create(){
return new PowerSteeringBelt();
}
}
}
class PetCreator extends Part{}
public class RegisteredFactories {
public static void main(String[] args){
for(int i=0;i<10;i++)
System.out.println(Part.createRandom());
}
}
基类Part包含一个工厂对象的列表。createRandom()随机创建对象。
7.instanceof与Class的等价性
instanceof保持了类型的概念,它指的是“你是这个类吗,或者你是这个类的派生类吗?”。如果用
==比较实际的Class对象,就没有考虑继承,它或者是这个确切的类型,或者不是。
8.反射
Class类与java.lang.reflect类库支持反射的概念,该类库包含了Field、Method、Constructor类。
9.动态代理
package c14;
import java.lang.reflect.*;
class DynamicProxyHandler implements InvocationHandler{
private Object proxied;
public DynamicProxyHandler(Object proxied){
this.proxied=proxied;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
return method.invoke(proxied,args);
}
}
public class SimpleDynamicProxy {
public static void consumer(Interface iface){
iface.doSomething();
iface.somethingElse("bonono");
}
public static void main(String[] args){
RealObject real=new RealObject();
consumer(real);
Interface proxy=(Interface)Proxy.newProxyInstance
(Interface.class.getClassLoader(),new Class[]{Interface.class},new DynamicProxyHandler(real));
consumer(proxy);
}
}
Proxy.newProxyInstance()可以创建动态代理,第一个参数需要一个类加载器,第二个参数是
希望代理实现的接口列表,最后一个参数是InvocationHandler接口的一个实现。
动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器的构造器传递一个“实际”
对象的引用,从而使得调用处理器在执行某中介任务时,可以将请求转发。
这里的调用处理器是DynamicProxyHandler。
10.空对象
创建一个标记接口
public interface Null {
}
创建一个NullPerson内部类,表示空对象
package c14;
public class Person {
public final String first;
public final String last;
public final String address;
public Person(String first,String last,String address){
this.first=first;
this.last=last;
this.address=address;
}
public String toString(){
return "Person: "+first+" "+last+" "+address;
}
public static class NullPerson extends Person implements Null{
private NullPerson(){super("None","None","None");}
public String toString(){ return "NullPerson";}
}
public static final Person NULL=new NullPerson();
}
package c14;
public class Position {
private String title;
private Person person;
public Position(String jobTitle,Person employee){
title=jobTitle;
person=employee;
if(person==null)
person=Person.NULL;
}
public Position(String jobTitle){
title=jobTitle;
person=Person.NULL;
}
public String getTitle(){ return title;}
public void setTitle(String newTitle){
title=newTitle;
}
public Person getPerson(){ return person;}
public void setPerson(Person newPerson){
person=newPerson;
if(person==null)
person=Person.NULL;
}
public String toString(){
return "Position: "+title+" "+person;
}
}
package c14;
import java.util.*;
public class Staff extends ArrayList<Position> {
public void add(String title,Person person){
add(new Position(title,person));
}
public void add(String... titles){
for(String title:titles)
add(new Position(title));
}
public Staff(String... titles){ add(titles);}
public boolean positionAvailable(String title){
for(Position position :this)
if(position.getTitle().equals(title)&& position.getPerson()==Person.NULL)
return true;
return false;
}
public void fillPosition(String title,Person hire){
for(Position position:this)
if(position.getTitle().equals(title)&&position.getPerson()==Person.NULL){
position.setPerson(hire);
return;
}
throw new RuntimeException("Position"+title+"not available");
}
public static void main(String[] args){
Staff staff=new Staff("President","CTO");
staff.fillPosition("President", new Person("Ne","Last","The Top"));
if(staff.positionAvailable("CTO"))
staff.fillPosition("CTO", new Person("Bob","Coder","Bright Light City"));
System.out.println(staff);
}
}
11.模拟对象与桩
都只是假扮可以传递实际信息的存活对象。 模拟对象往往是轻量级和自测试的,通常很多模拟
对象被创建出来是为了处理各种不同的测试情况。桩知识返回桩数据,它通常是重量级的,并
且经常在测试之间被复用。
12.接口与类型信息
反编译指令 javap -private C 可以反编译出类的所有成员
package c14;
import static tools.Print.*;
import c14.other.*;
import java.lang.reflect.*;
import c14.other.HiddenC;
class WithPrivateFinalField{
private int i=1;
private final String s="I'm totally safe";
private String s2="Am I safe?";
public String toString(){
return "i= "+i+", "+s+", "+s2;
}
}
public class ModifyingPrivateFields {
public static void main(String[] args)throws Exception{
WithPrivateFinalField pf=new WithPrivateFinalField();
print(pf);
Field f=pf.getClass().getDeclaredField("i");
f.setAccessible(true);
print("f.getInt(pf): "+f.getInt(pf));
f.setInt(pf,47);
print(pf);
}
}
通过使用反射,可以调用所有方法,字段,甚至是有private访问限定符的成员或包访问权限的成员。final域实际上
在遭遇修改时是安全的,实际上不会发生任何修改。这个技术通常用来做后门。