CoreJava 第6章 接口和内部类

1.克隆对象(深拷贝),复制对象,改原状态不会相互影响.

2.内部类:可访问外部类域,

3.代理(proxy) 实现任意接口的对象.

4.方法默认public,可定义常量(可认为没有实例域的抽象类)
实例类要声明public(默认包可见)

5.java是一种强类型的语言

6.实现Comparable接口可比较
要判断
if(getClass()!=o.getClass()){
  throw new ClassCastException();
}

7.接口变量引用实现接口类对象

8.if(object instanceof Comparable) 判断实现接口

9.接口扩展 public interface Powered extends Moveable

10.double SPEED=55;  ==( public static final) constrant(建议不书写多余关键字))

111.浅拷贝 除数字,基本类型外,其他引用
String类-不允许改变 --不同对象
Date可改变--有clone方法
数组.clone
11.Cloneable 只是作为标记(tagging interface),个人不建议这种写法
1)调用子对象的clone 可能修补深复制
2)Object有 protected Object clone()
子类调用重写 public Object clone();
j2se5 允许更改返回类型 public Employee clone();

3)深拷贝
public Employee clone() ..{
  Employee o=(Employee)super.clone();
  o.hireDated=(Date)hireDay.clone();
  return o;
}
4)实现clone不会抛出异常,编译器不知道 要throws
是final类的话 可try..catch

12.子类只能扩展一个抽象类

13.序列化 安全,容易,低效

14.接口与回调callback
定时器调用对象方法
函数指针对应产物--method对象
//java.util.Timer 主要用于调度后台
public class TimerTest {
	public static void main(String[] args) {
		System.out.println("start....");
		ActionListener listener=new TimePrinter();
		Timer t=new Timer(1000, listener);
		t.start(); 
		JOptionPane.showMessageDialog(null, "Quit Program?");//对话框
		System.exit(0);
	}
}

class TimePrinter implements ActionListener{

	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {
		System.out.println(new Date());
		Toolkit.getDefaultToolkit().beep();//蜂鸣
	}
}


15.内部类
a)访问外部类方法,域,这种引用在内部类不可见
类似于
public TimePrinter(Talking clock){
  outer=clock;
}
编译器为内部类添加默认构造器(修改内部类构造器)
外部类的实例方法自动添加this
ActionListener l=new TimePrinter(this);
明确指定内部类
ActionListener l=this.new TimePrinter();
编译器翻译为new TalkingClock$TimePrinter(this,null);
引用外部类.beep
if(TalkClock.this.beep) ...

内部类访问了外部域 会创建static access$0(outer) 方法获得外部域
b)对包中其他类隐藏
c)回调函数经常用anonymous

1)内部域只能被外围方法访问
2)内部类有指向外部实例的引用8
3)内部类实例由外部类构造才有


16.只有内部类可为私有,一般为包可见,public

166. 可在方法中定义局部类(在局部用到)(不能定义public private,被默认定义为块中可见)

17.内部类是一个编译器现象$间隔,与虚拟机无关
一种实例方法new TimerTest().new TimePrinter();

18.内部类访问方法局部变量(声明final)--传入参数被保存到局部变量
有时不只是局部用数组方式可保存值 final int[] counter=new int[1];

19.final被赋值一次,可不初始化

20.匿名内部类 方法不可引用,直接赋值给变量
ActionListener listener=new ActionListener(){//使用接口名或超类名
  public void actionPerformed(..){
   .......
  }
}

21.匿名内部类没类名,没构造器,可提供给超类构造器

22.静态内部类,不能引用外部类(有的用nested class)
内部公有类访问 ArrayLog.Pair
public static class Pair..


23.代理 运行时创建实现一组接口的类(编译时无法确定接口使用)
一种不好的方式 生成结果类,与编译器放一起,加载
代理:
1)实现指定接口全部方法
2)object的toString equals..hashCode()全部方法


不在运行时定义这些方法新代码,提供调用处理器,实现invokeHandler接口,
invoke方法调用代理对象方法

Proxy类的newProxyInstance
null表身默认类加载器
Class[] 每个元素都是要实现的接口
调用处理器

使用情况
a)路由对远程服务方法调用
b)运行期,由用户接口事件和动作关联
c)调试

public class TraceHandler implements InvocationHandler {
	private Object target;
	
	/**
	 * 
	 */
	public TraceHandler(Object t) {
		target=t;
	}

	/* (non-Javadoc)
	 * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.print(target);
		System.out.print("."+method.getName()+"(");
		if(args!=null){
			for(int i=0;i<args.length;i++){
				System.out.print(args[i]);
				if(i<args.length-1)
					System.out.print(",");
			}
			System.out.println(")");
		}
		return method.invoke(target, args);//只是调用,并不覆盖
		
	}
	
	public static void main(String[] args) {
		Object[] elements=new Object[1000];
		for(int i=0;i<elements.length;i++){
			Integer value=i+1;
			InvocationHandler handler=new TraceHandler(value);//代理类
			Class[] interfaces=new Class[]{Comparable.class};//接口
			elements[i]=Proxy.newProxyInstance(null, interfaces, handler);//代理对象  
		}
		Integer key=new Random().nextInt(elements.length)+1;
		int result=Arrays.binarySearch(elements, key);
		if(result>=0)
			System.out.println(elements[result]);
		

	}
}



24.代理类运行时创建,创建后是常规类
a)调用处理器--继承类(代理类只能有一个实例域)
b)代理类未定义类名的生成$Proxy开头类 Proxy.newProxyInstance..
c)特定类加载器,预设接口,只能有一个代理类 ,如上的到的是2/多个实例
d)一定是public final ,所有接口都public,既不属于特定包,否则接口,代理类要在同一包
Proxy.getProxyClass Proxy.isProxyClass









你可能感兴趣的:(java)