Java 语言中的美化类

标准 JavaAPI 中的一些类与其他类的处理方式略有不同。我说的是那些没有编译器和/或 JVM 的特殊支持就无法实现的类。

我马上想到的是:

  • Object(显然)因为它没有超类。
  • String作为语言对 + 运算符有特殊的支持。
  • 因为它有这个神奇的 start ()方法,尽管事实上没有字节码指令“分叉”执行。

我想所有这样的类都在 JLS 中以这样或那样的方式提到过。如果我说错了请纠正我。

无论如何,还有哪些类存在? Java 语言中有没有完整的“美化类”列表?

2559 次浏览

Class, of course. It has its own literals (a distinction it shares with String, BTW) and is the starting point of all that reflection magic.

All of the Number classes have a little bit of magic in the form of Autoboxing.

Since the important classes were mentioned, I'll mention some interfaces:

The Iterable interface (since 1.5) - it allows an object to participate in a foreach loop:

Iterable<Foo> iterable = ...;
for (Foo foo : iterable) {


}

The Serializable interface has a very special meaning, different from a standard interface. You can define methods that will be taken into account even though they are not defined in the interface (like readResolve()). The transient keyword is the language element that affects the behaviour of Serializable implementors.

  1. Throwable, RuntimeException, Error AssertionError
  2. References WeakReference, SoftReference, PhantomReference
  3. Enum
  4. Annotation
  1. Enum. You're not allowed to subclass it, but the compiler can.
  2. Many things under java.util.concurrent can be implemented without JVM support, but they would be a lot less efficient.

Most of those classes isn't really implemented with 'special' help from the compiler or JVM. Object does register some natives which poke around the internal JVM structures, but you can do that for your own classes as well. (I admit this is subject to semantics, "calls a native defined in the JVM" can be considered as special JVM support.)

What /is/ special is the behaviour of the 'new', and 'throw' instructions in how they initialise these internal structures.

Annotations and numbers are pretty much all-out freaky though.

Java array as in int[].class

Well since the special handling of assert has been mentioned. Here are some more Exception types which have special treatment by the jvm:

  • NullPointerException
  • ArithmeticException.
  • StackOverflowException
  • All kinds of OutOfMemoryErrors
  • ...

The exceptions are not special, but the jvm uses them in special cases, so you can't implement them yourself without writing your own jvm. I'm sure that there are more special exceptions around.

Not sure about this. But I cannot think of a way to manually implement IO objects.

There are a lot of different answers, so I thought it would be useful to collect them all (and add some):

Classes

  • AutoBoxing classes - the compiler only allows for specific classes
  • Class - has its own literals (int.class for instance). I would also add its generic typing without creating new instances.
  • String - with it's overloaded +-operator and the support of literals
  • Enum - the only class that can be used in a switch statement (soon a privilege to be given to String as well). It does other things as well (automatic static method creation, serialization handling, etc.), but those could theoretically be accomplished with code - it is just a lot of boilerplate, and some of the constraints could not be enforced in subclasses (e.g. the special subclassing rules) but what you could never accomplish without the priviledged status of an enum is include it in a switch statement.
  • Object - the root of all objects (and I would add its clone and finalize methods are not something you could implement)
  • References: WeakReference, SoftReference, PhantomReference
  • Thread - the language doesn't give you a specific instruction to start a thread, rather it magically applies it to the start() method.
  • Throwable - the root of all classes that can work with throw, throws and catch, as well as the compiler understanding of Exception vs. RuntimeException and Error.
  • NullPointerException and other exceptions such as ArrayIndexOutOfBounds which can be thrown by other bytecode instructions than athrow.

Interfaces

  • Iterable - the only interface that can be used in an enhanced for loop

Honorable mentions goes to:

  • java.lang.reflect.Array - creating a new array as defined by a Class object would not be possible.
  • Annotations They are a special language feature that behaves like an interface at runtime. You certainly couldn't define another Annotation interface, just like you can't define a replacement for Object. However, you could implement all of their functionality and just have another way to retrieve them (and a whole bunch of boilerplate) rather than reflection. In fact, there were many XML based and javadoc tag based implementations before annotations were introduced.
  • ClassLoader - it certainly has a privileged relationship with the JVM as there is no language way to load a class, although there is a bytecode way, so it is like Array in that way. It also has the special privilege of being called back by the JVM, although that is an implementation detail.
  • Serializable - you could implement the functionality via reflection, but it has its own privileged keyword and you would spend a lot of time getting intimate with the SecurityManager in some scenarios.

Note: I left out of the list things that provide JNI (such as IO) because you could always implement your own JNI call if you were so inclined. However, native calls that interact with the JVM in privileged ways are different.

Arrays are debatable - they inherit Object, have an understood hierarchy (Object[] is a supertype of String[]), but they are a language feature, not a defined class on its own.

sun.misc.unsafe is the mother of all dirty, spirit-of-the-language-breaking hacks.

java.lang.ClassLoader, though the actual dirty work is done by some unmentioned subclass (see 12.2.1 The Loading Process).

There is some magic in the System class.

System.arraycopy is a hook into native code

public static native void arraycopy(Object array1, int start1,
Object array2, int start2, int length);

but...

/**
* Private version of the arraycopy method used by the jit
* for reference arraycopies
*/
private static void arraycopy(Object[] A1, int offset1,
Object[] A2, int offset2, int length) {
...
}