@coldxiangyu
2017-06-16T14:47:19.000000Z
字数 2466
阅读 1326
java黑科技
看到标题,不免让人心生怀疑。接口难道可以new?
我们知道接口本身是用来定义标准的,具体实现由实现类来填充,使用的时候我们再实例化对应的接口的实现类。
严格来说,接口不能new。
但是我们可以通过匿名内部类的方式,无需创建独立的实现类,完成接口的实现。
比如我们常用的实现Runnable
接口启动线程的方式:
new Thread(new Runnable(){
@Override
public 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$1
implements 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$2
implements 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();
}
}
}
可以看到,其实匿名内部类其实都实现了各自的接口,只是在写法上更简单而已。