Ada*_*ski 15
您的问题应该是编译器如何处理标记接口,答案是:与任何其他接口没有区别.例如,假设我声明了一个新的标记接口Foo:
public interface Foo {
}
Run Code Online (Sandbox Code Playgroud)
...然后声明一个Bar实现的类Foo:
public class Bar implements Foo {
private final int i;
public Bar(int i) { this.i = i; }
}
Run Code Online (Sandbox Code Playgroud)
我现在能够Bar通过类型的引用引用一个实例Foo:
Foo foo = new Bar(5);
Run Code Online (Sandbox Code Playgroud)
...并且还检查(在运行时)对象是否实现Foo:
if (o instanceof Foo) {
System.err.println("It's a Foo!");
}
Run Code Online (Sandbox Code Playgroud)
后一种情况通常是使用标记接口的驱动因素; 前一种情况几乎没有什么好处,因为没有可以调用的方法Foo(没有先尝试向下转换).
那么JVM对于实现这个标记接口的类是如何处理的呢?
实现 Java 标记接口的类的实例受益于特定的行为,因为某些 JDK 类或 HotSpot JVM为它们提供了特定的行为。
以接口为例Serializable。
如果您深入研究ObjectOutputStream,ObjectInputStream您会发现序列化/反序列化行为是在 中实现的。
ObjectOutputStream.writeObject0()这是调用 by的片段,ObjectOutputStream.writeObject()说明了这一点:
public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants {
...
private void writeObject0(Object obj, boolean unshared) throws IOException {
...
if (obj instanceof String) {
writeString((String) obj, unshared);
} else if (cl.isArray()) {
writeArray(obj, desc, unshared);
} else if (obj instanceof Enum) {
writeEnum((Enum<?>) obj, desc, unshared);
} else if (obj instanceof Serializable) {
writeOrdinaryObject(obj, desc, unshared);
} else {
if (extendedDebugInfo) {
throw new NotSerializableException(
cl.getName() + "\n" + debugInfoStack.toString());
} else {
throw new NotSerializableException(cl.getName());
}
}
...
}
}
Run Code Online (Sandbox Code Playgroud)
对于Cloneable接口,查看Object.clone()方法,您将看到它引用了应用Cloneable规范的本机方法。
在HotSpot源代码中,src\share\vm\prims\jvm.cpp您可以找到Object.clone()实现:
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
const KlassHandle klass (THREAD, obj->klass());
JvmtiVMObjectAllocEventCollector oam;
// I skip all the processing that you can read in the actual source file
...
return JNIHandles::make_local(env, oop(new_obj));
JVM_END
Run Code Online (Sandbox Code Playgroud)
对于此标记接口,其行为不是直接在 JDK 类中实现,而是由 JVM 本身实现,但总体思路是相同的。
我们可以创建任何新的标记接口吗?
如果您创建自己的标记接口,则应该像 JVM 和 JDK 类那样处理实现 Java 标记接口的类的内置实例:即添加代码来专门处理标记接口的实例。
非常好的答案Adamski显示了这样做的总体思路。
| 归档时间: |
|
| 查看次数: |
13843 次 |
| 最近记录: |