接口中的所有方法自动地属于public。因此,在接口中声明方法时,不必提供关键字public。接口绝不能含有实例域,也不能在接口中实现方法。接口中的域将被自动设为public static final就是常量,在实现接口时,必须把方法声明为public;否则,编译器将认为这个方法的访问属性是包可见性,即类的默认访问属性。
接口不能实例化,但是可以声明变量,变量必须引用实现了接口的类对象。比如A是一个接口,Aa = new B();B必须实现了A。好像多态啊。
接口可以继承,类可以实现实现多个接口,只能继承一个类。instanceof可以用来判断是不是实现了接口。
拷贝是两个实例引用同一个对象,改变其中一个会另一个有影响。clone克隆是引用不同的对象,但是这两个实例的相等的,只要实例中没有可改变的子对象,那改变其中一个不会对另一个产生影响,子对象也用clone()方法就可以解决有可变子对象的情况。
对于类可以判断1.默认的clone方法是否满足要求。2.默认的clone方法是否能够通过调用可变子对象的clone得到修补。3.是否不应该使用clone.实际上,选项3是默认的。如果要选择1或2,类必须:实现Cloneable接口,使用public访问修饰符重新定义clone方法(Object类中的clone方法声明为protected)。
如果默认的clone()就可以实现的话,实现clone()方法就直接调用super.clone()就行了。
有子对象:
public xxx clone() throws xxx{抛出CloneNot-SupportException
xxx a = (xxx)super.clone();返回object
a.b = (b的类型)b.clone();b是可变子对象,string不可变。
return a;
}
需要谨慎使用克隆。数组也有clone(),public类型的
内部类
普通内部类声明:B是A的内部类,Aa =new A();A.B b = a.new B();
1.内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据
2.内部类可以对同一个包中的其他类隐藏起来。
3.当想要定义一个回调函数且不想编写大量代码时,使用匿名( anonymous)内部类比较便捷。
局部类不能用public或private访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。局部类有一个优势,即对外部世界可以完全地隐藏起来。局部类访问局部变量,那些局部变量必须被声明为final。
由于构造器的名字必须与类名相同,而匿名类没有类名,所以,匿名类不能有构造器。取而代之的是,将构造器参数传递给超类(superclass)构造器。尤其是在内部类实现接口的时候,不能有任何构造参数,因为没有没有构造函数。
在内部类不需要访问外围类对象的时候,应该使用静态内部类。
声明在接口中的内部类自动成为static和public。
实现comparable接口,里面有compareTo();可以重写比较。
代理
利用代理可以在运行时创建一个实现了一组给定接口的新类。这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用。
代理类要实现指定接口所需要的全部方法。Object类中的全部方法,例如, toString、 equals等。
代理类是在程序运行过程中创建的。所有的代理类都扩展于Proxy类。一个代理类只有一个实例域—调用处理器,它定义在Proxy的超类中。为了履行代理对象的职责,所需要的任何附加数据都必须存储在调用处理器中。
对于特定的类加载器和预设的一组接口来说,只能有一个代理类。也就是说,如果使用同一个类加载器和接口数组调用两次newProxyInstance方法的话,那么只能够得到同一个类的两个对象。
代理类一定是public和final。如果代理类实现的所有接口都是public,代理类就不属于某个特定的包;否则,所有非公有的接口都必须属于同一个包,同时,代理类也属于这个包。可以通过调用Proxy类中的isProxyClass方法检测一个特定的Class对象是否代表一个代理类。
下面的例子使用代理对象对二分查找进行跟踪
package test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Random;
public class Test{
public static void main(String[] args) {
Object[] element = new Object[1000];
for(int i=0;i<element.length;i++){
Integer value=i+1;
InvocationHandler handler = new T(value);
Object proxy = Proxy.newProxyInstance(null, new Class[]{Comparable.class},handler);
element[i]=proxy;
}
Integer key = new Random().nextInt(element.length)+1;
int result = Arrays.binarySearch(element, key);
if(result>=0)
System.out.println(element[result]);
}
}
class T implements InvocationHandler {
private Object target;
T(Object a){
target = a;
}
public Object invoke(Object proxy,Method m,Object[] args)throws Throwable{
System.out.print(target);
System.out.print(","+m.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 m.invoke(target, args);
}
}
结果为
500,compareTo(187)
250,compareTo(187)
125,compareTo(187)
187,compareTo(187)
187,toString()
187
代理类实现了comparable接口,所以invoke就是compareTo方法。