📄 chapter02.html
字号:
value (as in C and C++); it will not automatically be initialized to zero. You
are responsible for assigning an appropriate value before you use <B>x</B>. If
you forget, Java definitely improves on C++: you get a compile-time error
telling you the variable might not have been initialized. (Many C++ compilers
will warn you about uninitialized variables, but in Java these are
errors.)</FONT><A NAME="_Toc375545227"></A><A NAME="_Toc408018428"></A><BR></P></DIV>
<A NAME="Heading73"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Methods, arguments <BR>and return values</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Up until now, the term
<I>function</I> has been used to describe a named subroutine. The term that is
more commonly used in Java is <I>method,</I> as in “a way to do
something.” If you want, you can continue thinking in terms of functions.
It’s really only a syntactic difference, but from now on
“method” will be used in this book rather than
“function.”</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Methods in Java determine the
messages an object can receive. In this section you will learn how simple it is
to define a method.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The fundamental parts of a method
are the name, the arguments, the return type, and the body. Here is the basic
form:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>returnType methodName( <font color=#009900>/* argument list */</font> ) {
<font color=#009900>/* Method body */</font>
}</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The return type is the type of the
value that pops out of the method after you call it. The method name, as you
might imagine, identifies the method. The argument list gives the types and
names for the information you want to pass into the method.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Methods in Java can be created only
as part of a class. A method can be called only for an
object,</FONT><A NAME="fnB13" HREF="#fn13">[13]</A><FONT FACE="Georgia">
and that object must be able to perform that method call. If you try to call the
wrong method for an object, you’ll get an error message at compile time.
You call a method for an object by naming the object followed by a period (dot),
followed by the name of the method and its argument list, like this:
<B>objectName.methodName(arg1, arg2, arg3)</B>. For example, suppose you have a
method <B>f( )</B> that takes no arguments and returns a value of type
<B>int</B>. Then, if you have an object called <B>a</B> for which
<B>f( )</B> can be called, you can say this:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>int</font> x = a.f();</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The type of the return value must
be compatible with the type of <B>x</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This act of calling a method is
commonly referred to as <I>sending a message to an object</I>. In the above
example, the message is <B>f( )</B> and the object is <B>a</B>.
Object-oriented programming is often summarized as simply “sending
messages to
objects.”</FONT><A NAME="_Toc375545228"></A><A NAME="_Toc408018429"></A><BR></P></DIV>
<A NAME="Heading74"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
The argument list</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The method argument list specifies
what information you pass into the method. As you might guess, this information
– like everything else in Java – takes the form of objects. So, what
you must specify in the argument list are the types of the objects to pass in
and the name to use for each one. As in any situation in Java where you seem to
be handing objects around, you are actually passing
handles.</FONT><A NAME="fnB14" HREF="#fn14">[14]</A><FONT FACE="Georgia">
The type of the handle must be correct, however. If the argument is supposed to
be a <B>String</B>, what you pass in must be a string.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Consider a method that takes a
string as its argument. Here is the definition, which must be placed within a
class definition for it to compile:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>int</font> storage(String s) {
<font color=#0000ff>return</font> s.length() * 2;
}</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This method tells you how many
bytes are required to hold the information in a particular <B>String. </B>(Each
<B>char </B>in a <B>String </B>is 16 bits, or two bytes, long, to support
Unicode characters.) The argument is of type <B>String</B> and is called
<B>s</B>. Once <B>s</B> is passed into the method, you can treat it just like
any other object. (You can send messages to it.) Here, the <B>length( )</B>
method is called, which is one of the methods for <B>String</B>s; it returns the
number of characters in a string.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can also see the use of the
<B>return</B> keyword, which does two things. First, it means “leave the
method, I’m done.” Second, if the method produces a value, that
value is placed right after the <B>return</B> statement. In this case, the
return value is produced by evaluating the expression <B>s.length( ) *
2</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can return any type you want,
but if you don’t want to return anything at all, you do so by indicating
that the method returns <B>void</B>. Here are some examples:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>boolean</font> flag() { <font color=#0000ff>return</font> <font color=#0000ff>true</font>; }
<font color=#0000ff>float</font> naturalLogBase() { <font color=#0000ff>return</font> 2.718; }
<font color=#0000ff>void</font> nothing() { <font color=#0000ff>return</font>; }
<font color=#0000ff>void</font> nothing2() {}</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When the return type is
<B>void</B>, then the <B>return</B> keyword is used only to exit the method, and
is therefore unnecessary when you reach the end of the method. You can return
from a method at any point, but if you’ve given a non-<B>void </B>return
type then the compiler will ensure that you return the appropriate type of value
regardless of where you return.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At this point, it can look like a
program is just a bunch of objects with methods that take other objects as
arguments and send messages to those other objects. That is indeed much of what
goes on, but in the following chapter you’ll learn how to do the detailed
low-level work by making decisions within a method. For this chapter, sending
messages will
suffice.</FONT><A NAME="_Toc375545229"></A><A NAME="_Toc408018430"></A><BR></P></DIV>
<A NAME="Heading75"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Building a Java program</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There are several other issues you
must understand before seeing your first Java
program.</FONT><A NAME="_Toc375545230"></A><A NAME="_Toc408018431"></A><BR></P></DIV>
<A NAME="Heading76"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Name visibility</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A problem in any programming
language is the control of names. If you use a name in one module of the
program, and another programmer uses the same name in another module, how do you
distinguish one name from another and prevent the two names from
“clashing”? In C this is a particular problem because a program is
often an unmanageable sea of names. C++ classes (on which Java classes are
based) nest functions within classes so they cannot clash with function names
nested within other classes. However, C++ still allowed global data and global
functions, so clashing was still possible. To solve this problem, C++ introduced
<I>namespaces</I> using additional keywords.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Java was able to avoid all of this
by taking a fresh approach. To produce an unambiguous name for a library, the
specifier used is not unlike an Internet domain name. In fact, the Java creators
want you to use your Internet domain name in reverse since those are guaranteed
to be unique. Since my domain name is <B>BruceEckel.com</B>, my utility library
of foibles would be named <B>com.bruceeckel.utility.foibles</B>. After your
reversed domain name, the dots are intended to represent
subdirectories.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <A NAME="Index76"></A>Java 1.0
and Java 1.1<A NAME="Index77"></A> the domain extension <B>com</B>, <B>edu</B>,
<B>org</B>, <B>net</B>, etc., was
<A NAME="Index78"></A><A NAME="Index79"></A>capitalized by convention, so the
library would appear: <B>COM.bruceeckel.utility.foibles</B>. Partway through the
development of Java 1.2<A NAME="Index80"></A>, however, it was discovered that
this caused problems and so now the entire package name is
lowercase.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This mechanism in Java means that
all of your files automatically live in their own namespaces, and each class
within a file automatically has a unique identifier. (Class names within a file
must be unique, of course.) So you do not need to learn special language
features to solve this problem – the language takes care of it for
you.</FONT><A NAME="_Toc375545231"></A><A NAME="_Toc408018432"></A><BR></P></DIV>
<A NAME="Heading77"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Using other components</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Whenever you want to use a
predefined class in your program, the compiler must know how to locate it. Of
course, the class might already exist in the same source code file that
it’s being called from. In that case, you simply use the class –
even if the class doesn’t get defined until later in the file. Java
eliminates the “forward referencing” problem so you don’t need
to think about it.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">What about a class that exists in
some other file? You might think that the compiler should be smart enough to
simply go and find it, but there is a problem. Imagine that you want to use a
class of a particular name, but the definition for that class exists in more
than one file. Or worse, imagine that you’re writing a program, and as
you’re building it you add a new class to your library that conflicts with
the name of an existing class.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To solve this problem, you must
eliminate all potential ambiguities. This is accomplished by telling the Java
compiler exactly what classes you want using the <B>import</B> keyword.
<B>import </B>tells the compiler to bring in a <I>package</I>, which is a
library of classes. (In other languages, a library could consist of functions
and data as well as classes, but remember that all code in Java must be written
inside a class.) </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Most of the time you’ll be
using components from the standard Java libraries that come with your compiler.
With these, you don’t need to worry about long, reversed domain names; you
just say, for example:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>import</font> java.util.Vector;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">to tell the compiler that you want
to use Java’s <B>Vector</B> class. However, <B>util</B> contains a number
of classes and you might want to use several of them without declaring them all
explicitly. This is easily accomplished by using ‘<B>*</B>’ to
indicate a wildcard:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>import</font> java.util.*;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It is more common to import a
collection of classes in this manner than to import classes
individually.</FONT><A NAME="_Toc375545232"></A><A NAME="_Toc408018433"></A><BR></P></DIV>
<A NAME="Heading78"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
The static keyword</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Ordinarily, when you create a class
you are describing how objects of that class look and how they will behave. You
don’t actually get anything until you create an object of that class with
<B>new</B>, and at that point data storage is created and methods become
available.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">But there are two situations in
which this approach is not sufficient. One is if you want to have only one piece
of storage for a particular piece of data, regardless of how many objects are
created, or even if no objects are created. The other is if you need a method
that isn’t associated with any particular object of this class. That is,
you need a method that you can call even if no objects are created. You can
achieve both of these effects with the <B>static</B> keyword. When you say
something is <B>static</B>, it means that data or method is not tied to any
particular object instance of that class. So even if you’ve never created
an object of that class you can call a <B>static</B> method or access a piece of
<B>static</B> data. With ordinary, non-<B>static</B> data and methods you must
create an object and use that object to access the data or method, since
non-<B>static</B> data and methods must know the particular object they are
working with. Of course, since <B>static</B> methods don’t need any
objects to be created before they are used, they cannot <I>directly </I>access
non-<B>static</B> members or methods by simply calling those other members
without referring to a named object (since non-<B>static</B> members and methods
must be tied to a particular object).</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Some object-oriented languages use
the terms <I>class data</I> and <I>class methods</I>, meaning that the data and
methods exist only for the class as a whole, and not for any particular objects
of the class. Sometimes the Java literature uses these terms
too.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To make a data member or method
<B>static</B>, you simply place the keyword before the definition. For example,
this produces a <B>static</B> data member and initializes it:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>class</font> StaticTest {
<font color=#0000ff>static</font> <font color=#0000ff>int</font> i = 47;
}</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Now even if you make two
<B>StaticTest</B> objects, there will still be only one piece of storage for
<B>StaticTest.i.</B> Both objects will share the same <B>i.
</B>Consider:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>StaticTest st1 = <font color=#0000ff>new</font> StaticTest();
StaticTest st2 = <font color=#0000ff>new</font> StaticTest();</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At this point, both <B>st1.i</B>
and <B>st2.i</B> have the same value of 47 since they refer to the same piece of
memory.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There are two ways to refer to a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -