📄 tij0198.html
字号:
is called by the garbage collector and is supposed to be responsible only for
releasing "resources" (such as open files, sockets, ports, URLs, etc). If you
need something done at a specific point, you must create a special method and
call it, not rely upon
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Put another way, all objects in C++ will be (or rather, should be) destroyed,
but not all objects in Java are garbage collected. Because Java doesn’t
support destructors, you must be careful to create a cleanup method if
it’s necessary and to explicitly call all the cleanup methods for the
base class and member objects in your class.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Java
has method overloading that works virtually identically to C++ function
overloading.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Java
does not support default arguments.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> There’s
no
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>goto</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in Java. The one unconditional jump mechanism is the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>break
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>label</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>continue
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>label</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which is used to jump out of the middle of multiply-nested loops.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Java
uses a singly-rooted hierarchy, so all objects are ultimately inherited from
the root class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
In C++, you can start a new inheritance tree anywhere, so you end up with a
forest of trees. In Java you get a single ultimate hierarchy. This can seem
restrictive, but it gives a great deal of power since you know that every
object is guaranteed to have at least the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
interface. C++ appears to be the only OO language that does not impose a singly
rooted hierarchy.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Java
has no templates or other implementation of parameterized types. There is a set
of collections:
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Stack</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Hashtable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that hold
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
references, and through which you can satisfy your collection needs, but these
collections are not designed for efficiency like the C++ Standard Template
Library (STL). The new collections in Java 1.2 are more complete, but still
don’t have the same kind of efficiency as template implementations would
allow.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Garbage
collection means memory leaks are much harder to cause in Java, but not
impossible. (If you make native method calls that allocate storage, these are
typically not tracked by the garbage collector.) However, many memory leaks and
resouce leaks can be tracked to a badly written
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">or
to not releasing a resource at the end of the block where it is allocated (a
place where a destructor would certainly come in handy). The garbage collector
is a huge improvement over C++, and makes a lot of programming problems simply
vanish. It might make Java unsuitable for solving a small subset of problems
that cannot tolerate a garbage collector, but the advantage of a garbage
collector seems to greatly outweigh this potential drawback.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Java
has built-in multithreading support. There’s a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class that you inherit to create a new thread (you override the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method). Mutual exclusion occurs at the level of objects using the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword as a type qualifier for methods. Only one thread may use a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method of a particular object at any one time. Put another way, when a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method is entered, it first “locks” the object against any other
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method using that object and “unlocks” the object only upon exiting
the method. There are no explicit locks; they happen automatically.
You’re still responsible for implementing more sophisticated
synchronization between threads by creating your own “monitor”
class. Recursive
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods work correctly. Time slicing is not guaranteed between equal priority
threads.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Instead
of controlling blocks of declarations like C++ does, the access specifiers (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
are placed on each definition for each member of a class. Without an explicit
access specifier, an element defaults to “friendly,” which means
that it is accessible to other elements in the same package (equivalent to them
all being C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>friend</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s)
but inaccessible outside the package. The class, and each method within the
class, has an access specifier to determine whether it’s visible outside
the file. Sometimes the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">keyword
is used less in Java because “friendly” access is often more useful
than excluding access from other classes in the same package. (However, with
multithreading the proper use of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is essential.) The Java
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword means “accessible to inheritors
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>and</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to others in this package.” There is no equivalent to the C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">keyword
that means “accessible to inheritors
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>
only
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">”
(
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private
protected
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
used to do this, but the use of that keyword pair was removed).
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Nested
classes. In C++, nesting a class is an aid to name hiding and code organization
(but C++ namespaces eliminate the need for name hiding). Java packaging
provides the equivalence of namespaces, so that isn’t an issue. Java 1.1<A NAME="Index3126"></A>
has
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>inner
classes
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that look just like nested classes. However, an object of an inner class
secretly keeps a handle to the object of the outer class that was involved in
the creation of the inner class object. This means that the inner class object
may access members of the outer class object without qualification, as if those
members belonged directly to the inner class object. This provides a much more
elegant solution to the problem of callbacks, solved with pointers to members
in C++.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Because
of inner classes described in the previous point, there are no pointers to
members in Java.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> No
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>inline</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods. The Java compiler might decide on its own to inline a method, but you
don’t have much control over this. You can suggest inlining in Java by
using the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword for a method. However,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>inline</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
functions are only suggestions to the C++ compiler as well.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Inheritance
in Java has the same effect as in C++, but the syntax is different. Java uses
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>extends</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword to indicate inheritance from a base class and the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword to specify methods to be called in the base class that have the same
name as the method you’re in. (However, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword in Java allows you to access methods only in the parent class, one
level up in the hierarchy.) Base-class scoping in C++ allows you to access
methods that are deeper in the hierarchy). The base-class constructor is also
called using the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword. As mentioned before, all classes are ultimately automatically
inherited from
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There’s
no explicit constructor initializer list like in C++, but the compiler forces
you to perform all base-class initialization at the beginning of the
constructor body and it won’t let you perform these later in the body.
Member initialization is guaranteed through a combination of automatic
initialization and exceptions for uninitialized object handles.
</FONT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">public
class Foo extends Bar {
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
public Foo(String msg) {
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
super(msg); // Calls base constructor
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
}
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
public baz(int i) { // Override
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
super.baz(i); // Calls base method
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
}
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">}</FONT></TT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Inheritance
in Java doesn’t change the protection level of the members in the base
class. You cannot specify
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
inheritance in Java, as you can in C++. Also, overridden methods in a derived
class cannot reduce the access of the method in the base class. For example, if
a method is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in the base class and you override it, your overridden method must also be
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(the compiler checks for this).
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Java
provides the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword, which creates the equivalent of an abstract base class filled with
abstract methods and with no data members. This makes a clear distinction
between something designed to be just an interface and an extension of existing
functionality via the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>extends</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword. It’s worth noting that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword produces a similar effect in that you can’t create an object of
that class. An
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>may</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
contain abstract methods (although it isn’t required to contain any), but
it is also able to contain implementations, so it is restricted to single
inheritance. Together with interfaces, this scheme prevents the need for some
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -