Thking in java(第四版)-查缺补漏(第14章)

背景

继续查缺补漏。

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域实际上

在遭遇修改时是安全的,实际上不会发生任何修改。这个技术通常用来做后门。

猜你喜欢

转载自blog.csdn.net/a614528195/article/details/81742775
今日推荐