@coldxiangyu
2017-06-16T06:47:19.000000Z
字数 2466
阅读 1483
java黑科技
看到标题,不免让人心生怀疑。接口难道可以new?
我们知道接口本身是用来定义标准的,具体实现由实现类来填充,使用的时候我们再实例化对应的接口的实现类。
严格来说,接口不能new。
但是我们可以通过匿名内部类的方式,无需创建独立的实现类,完成接口的实现。
比如我们常用的实现Runnable接口启动线程的方式:
new Thread(new Runnable(){@Overridepublic void run(){......}}).start();
这样的写法,大大的简化了我们的代码,否则,我们需要单独定义Runnable的实现类。
还有我们常用的动态代理,其实也可以使用匿名内部类的方式,正常情况下我们定义InvocationHandler的实现类,进行代理方法invoke方法的重写。实际上我们完全可以通过下面的代码实现:
Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {//..........}}
这样,我们就省去了InvocationHandler接口实现类的开销。
实际上在我们的类编译class的时候,匿名内部类也是单独编译成class文件的,见下图:
我们对匿名内部类进行反编译:
package com.lxy.rpc.framework;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Method;import java.net.Socket;final class RpcFramework$1implements Runnable{public void run(){try{try{ObjectInputStream input = new ObjectInputStream(this.val$socket.getInputStream());try {String methodName = input.readUTF();Class[] parameterTypes = (Class[])(Class[])input.readObject();Object[] arguments = (Object[])(Object[])input.readObject();ObjectOutputStream output = new ObjectOutputStream(this.val$socket.getOutputStream());try {Method method = this.val$service.getClass().getMethod(methodName, parameterTypes);Object result = method.invoke(this.val$service, arguments);output.writeObject(result);output.writeUTF("123123");} catch (Throwable t) {output.writeObject(t);} finally {output.close();}} finally {input.close();}} finally {this.val$socket.close();}} catch (Exception e) {e.printStackTrace();}}}
package com.lxy.rpc.framework;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.PrintStream;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.net.Socket;final class RpcFramework$2implements InvocationHandler{public Object invoke(Object proxy, Method method, Object[] arguments)throws Throwable{Socket socket = new Socket(this.val$host, this.val$port);try {ObjectOutputStream output;try {output.writeUTF(method.getName());output.writeObject(method.getParameterTypes());output.writeObject(arguments);ObjectInputStream input;try {Object result = input.readObject();System.out.println(input.readUTF());if (result instanceof Throwable) {throw ((Throwable)result);}Object localObject1 = result;input.close();output.close();return localObject1;}finally{input.close();}} finally {output.close();}} finally {socket.close();}}}
可以看到,其实匿名内部类其实都实现了各自的接口,只是在写法上更简单而已。