| Home > Core Java FAQ
> Language Fundamentals FAQ |
| Java
Fundamentals |
| Basic(19) * Constants
and Expressions(40) * Variables and Methods(16)
* Array(11) * Date/Time(36)
* Compile Time(11) * Run
Time(02) * C-vs-Java(12) |
| |
|
Q .
Are Java objects pointers?
|
Ans :
No; Java
objects are objects (typed containers for data plus associated
methods), but the Java language lets you access objects only via
references.
The
Java runtime is filled with objects-created by the system and by
your program. An object is a programming entity that holds data
and is associated with a class; the class defines both the data
and services that its objects support.
Although objects are the heart of
your Java program, you never get direct access to them. The Java
language lets you handle only object references-values that refer
to objects but completely lack arithmetic (pointer-like)
properties . Whenever a variable, method argument, or method
return value appears to work with an object, it is in fact working
indirectly through an object reference.
|
|
Q .
In a method invocation, does Java pass arguments by reference or by value?
|
Ans
:
Java method
invocations pass arguments by value.
Java
method invocations pass all arguments by value-primitive
data types and reference data types alike. This means that the
value of each argument is copied to a corresponding
method-internal variable before the method's code is executed. The
method's code can act only on this internal copy of the data.
Consider the following minimal
class, which defines and invokes a zeroIt method:
class Example {
static void zeroIt(int intVal) {
intVal = 0;
}
public static void main(String[] args) {
int myInt = 5;
zeroIt(myInt);
System.out.println("Does myInt equal 0 or 5? " + myInt);
}
}
Running this class
shows that the int argument is unchanged:
> java Example
Does myInt equal 0 or 5? 5
Because zeroIt's
int argument is passed by value, zeroIt
zeroes only its internal copy of the int value; it
doesn't affect the original int value stored in myInt.
What about objects, then? The key
here is that the Java language provides only reference-type
(pointer-like) variables for objects. The values of such variables
are not objects, but references to objects. When you invoke a
method with object-like arguments, the object references are
passed by value; in other words, the reference itself is copied to
a corresponding method-internal variable. The result is that two
different references now refer to the same object.
Copying references still allows you
to affect the referred-to object from inside the method, as long
as the internal reference copy keeps referring to the original
object. Consider a slightly different class, ZeroItExample2,
that works on StringBuffer instances (modifiable
character strings ):
class Example2 {
static void zeroIt(StringBuffer buf) {
buf.setLength(0);
buf.append("0");
}
public static void main(String[] args) {
StringBuffer myStringBuffer = new StringBuffer("abc");
zeroIt(myStringBuffer);
System.out.println("Does myStringBuffer equal abc or 0? "
+ myStringBuffer);
}
}
The answer this
time is:
> java Example2
Does myStringBuffer equal abc or 0? 0
Here, the zeroIt
method does affect data outside the method, but only because it
could reach it indirectly, via the reference copied in.
As a final exercise, try replacing zeroIt
in Example2 with the following tryToZeroIt
method:
static void tryToZeroIt(StringBuffer buf) {
buf = new StringBuffer("0");
}
Why does this
version not affect the value of myStringBuffer?
(Hint: Consider which operations in zeroIt and tryToZeroIt
affect references and which affect referred-to objects.)
|
|
Q . How do you parse commandline arguments to a Java program?
|
Ans
:
Perhaps surprisingly, commandline arguments are not encouraged, as
they make a program not 100% pure Java. The reason is that some systems
like MacOS don't normally have a command line or command-line arguments. Consider using properties instead so that your programs fit
more naturally into the environment.
If you must use command-line arguments, have them comply with the POSIX conventions, i.e. they should
See
http://java.sun.com/docs/books/tutorial/essential/attributes/_posix.html
If such arguments are used, it should NOT be up to the invocating application
(ie java.exe) to propperly parse them. According to the getopts routine from gnu, getopts is required to know exactly what the
usable parameters are before it can properly parse them and create argc/argv.
Because of that, it becomes unduly hard for calling programs such as java.exe to properly parse class arguments by themselves. Instead, they
should create an argc/argv pair (actually a java specific array
dependant on the way in which the method is called) where the number of elements equals the number of text words in the options. Text word
means a group of ascii characters outside of quotation marks, not separated by white space. Once these text words are passed to the
class, it is up to the class to actually parse them correctly.
The text words passed to the class can be parsed however the class author wishes. It is up to the author to correctly parse the options.
There are several implementations of getopts which perform such
parsing, in C, Perl, and Java. You will find one at http://www.urbanophile.com/arenn/hacking/download.html#getopt
|
|
Q . How do I send a variable number of arguments to a method?
|
Ans
: 1. (Easy) Use method overloading to support different parameters.This makes things easy on the caller but can get out of hand if
you want to support a wide number and variety of parameter types.
You should ask yourself if your code design is well-organized if you need to do this.
2. (More complicated) Use arrays. It's even possible to declare arrays inline as shown below:
foo("A param",
new Object[] {"param3", "param4", new Integer(5)} );
// ...
void foo(String param1, Object param2[]) {
System.out.println(param1);
for (int i = 0; i < param2.length; i++) {
System.out.println(param2[i].toString());
}
}
You can even pass arrays of arrays using this method. Of course, inside the method you need to be able to decode what the arguments
are and how you use them.
3. Alternatively you can invent a class that just contains all the possible fields you might want to pass into a method (plus
booleans to say if each field is set or not), and make an object of that class be a parameter to the method. You can return
multiple values from a method the same ways; either have the
method return an array or a wrapper object.
However, remember the wise words of Professor Alan Perlis, "if your procedure has more than about half a dozen parameters, you probably
forgot a few." Passing large numbers of arguments into a function
suggests your function is badly organized.
|
|
Q . How can I return a different object in a method parameter?
|
Ans : There are two ways. The obvious way is "just add another level of
indirection". Wrap the object in another class, whose purpose is simply
to be passed as a parameter, allowing the nested object reference to be
modified.
The second alternative is a clearer variant of this. Pass in a single
element array. Since arrays are objects, this works.
void jfoo(Object ref[]){
ref[0] = new Object();
}
...
Object kludge[] = new Object[1];
kludge[0]= myObj;
jfoo(kludge);
if (kludge[0] == myObj) ...
else ...
Note that changing a global variable/object inside a method is an egregious programming practice; it usually violates basic OOP
constructs.
|
|
Q . How can I pass an object to a method, and have the method change the
reference so it points to a different object back in the calling code?
|
Ans
: Same as Above..
|
|
Q . How can you send a function pointer as an argument?
|
Ans
: Simple answer: use a "callback". Make the parameter an interface
and pass an argument instance that implements that interface.
public interface CallShow { public void Show( ); }
public class ShowOff implements CallShow {
public void Show( ) { .... }
public class ShowOff2 implements CallShow {
public void Show( ) { .... }
public class UseShow {
CallShow savecallthis;
UseShow( CallShow withthis ) {
savecallthis = withthis;
}
void ReadyToShow( ) { savecallthis.Show( ); }
}
// in some other class that uses all this stuff:
UseShow use_1 = new UseShow( new ShowOff() );
UseShow use_2 = new UseShow( new Showoff2() );
and then the ReadyToShow() method on use_1 or use_2 will call the appropriate method, as if you had stored a pointer to the method.
|
|
Q .
How do I pass a function pointer to a method?
|
Ans
:
Methods are not first class objects in Java. Only objects and primitive data types can be passed to methods.
Instead you should declare an interface which declares the function you want to pass; for example
public interface Comparable {
public abstract int compare(Object o1, Object o2);
}
Then declare that your method takes an object of this type. For example,
public void sort(Object[] o, Comparable c) {
boolean done = false;
while (!done) {
done = true;
for (int i = 0; i < o.length - 1; i++) {
if (c.compare(o[i], o[i+1]) < 0) {
swap(o[i], o[i+1]);
done = false;
}
}
}
}
Each class you want to compare then needs its own class which implements Comparable. For example,
public class StringCompare implements Comparable {
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
return s1.compareTo(s2);
}
}
It helps that Object is a super class for all object types.
|
|
Q . If the Java language lacks pointers, how do I implement classic pointer structures like linked lists?
|
Ans
: Use object references in place of
pointers.
Object references in Java are like object pointers minus the arithmetic. The Java language lets you point to (refer to) objects; it just doesn't let you change numbers into references, references into numbers, or otherwise treat references in any numerical way. This property makes it straightforward to implement classic pointer-dependent data structures such as lists and trees. The following example shows a minimal linked-list implementation of a stack:
/** A bare-bones stack class that holds objects of any class. */
public class SimpleStack {
LinkedObject stackTop = null;
public void push(Object obj) {
if (obj != null) {
stackTop = new LinkedObject(obj, stackTop);
}
}
public Object pop() {
if (stackTop != null) {
Object oldTop = stackTop.value;
stackTop = stackTop.nextObject;
return oldTop;
}
return null;
}
}
/** A bare-bones class for linking objects of any class. */
class LinkedObject {
Object value;
LinkedObject nextObject;
LinkedObject(Object obj, LinkedObject next) {
value = obj;
nextObject = next;
}
}
Even better, you often don't need to reinvent the wheel; you can use a class that's already been
designed to provide the behavior you need. A Stack class already exists in the java.util package, for example. The java.util package also provides a Vector class, which represents a growable array for Object instances that you can use in place of a linked list, at least for some applications. The above code, for instance, could be rewritten as:
import java.util.Vector;
public class VectorStack {
Vector stackElements;
public void push(Object obj) {
if (obj != null) {
stackElements.addElement(obj);
}
}
public Object pop() {
if (stackElements.isEmpty()) {
return null;
}
Object oldTop = stackElements.lastElement();
stackElements.removeElementAt(stackElements.size() - 1);
return oldTop;
}
}
|
|
Q . What does it mean that a method or field is "static"?
|
Ans
: Static variables and methods are instantiated only once per class. In other words they are class variables, not instance variables. If you change the value of a static variable in a particular object, the value of that variable changes for all instances of that class.
Static methods can be referenced with the name of the class rather than the name of a particular object of the class (though that works too). That's how library methods like System.out.println() work. out is a static field in the java.lang.System class.
|
|
Q .
What does the following error message mean: Can't make a static reference to nonstatic variable?
|
Ans
: The compiler is complaining that you are trying to reference the implicit instance variable this from within a class method.
The Java language lets you define three kinds of variables: class variables, instance variables, and local variables (Q1.5). Class variables are defined on a per-class basis, and all instances of a class can access them. Instance variables are defined on a one-per-object basis, and you can access them only in connection with some specific instance of a class. Local variables are defined inside individual methods and can be accessed only from inside that same method.
The "Can't make a static reference ..." error message most commonly arises in a class's main(String[]) method, which the Java language requires to be a class method (declared with the static keyword; see Q1.6). The following code exemplifies the error:
/* The compiler will complain about this: */
class StaticError {
String myString = "hello";
public static void main(String[] args) {
System.out.println(myString);
}
}
The myString variable is an instance variable; you cannot access it unless you have created one or more instances of the class. There are therefore two minimal ways to fix the example: either change the variable to be a class variable, or create an instance of the class in order to access the instance variable.
The first fix simply requires that you use the static keyword when defining the variable:
/* This works. */
class NoStaticError {
static String myString = "hello";
public static void main(String[] args) {
System.out.println(myString);
}
}
The second fix requires creation of an instance of the class:
/* This also works. */
class NoStaticError2 {
String myString = "hello";
public static void main(String[] args) {
NoStaticError2 obj = new NoStaticError2();
System.out.println(obj.myString);
}
}
|
|
Q .
In a class method, how can I get the name of the class, or create a new instance of the class?
|
Ans
:
You can't, in general; these operations require that you obtain an instance of class Class representing the current class, which in turn requires that you either (a) already know the name of the class, or (b) already have an instance of the class.
The Java platform includes a special class, the Class class, that lets your program inspect Java data types at run time. Each instance of class Class represents a different class or interface type that has been loaded into the current Java Virtual Machine.
You can query a Class instance for many kinds of information about the class. In the JDK 1.0.2, you can query the class's name, class loader, superclass, and interfaces; you can also create a new instance of the class with the newInstance method. The JDK 1.1 opens much more to inspection, including the class's fields, methods (Q2.16), and constructors.
One way to obtain a Class instance is to ask for it by name, using the forName method (Q3.7). The following code, for example, fetches three distinct Class instances from the virtual machine:
Class c1 = null;
Class c2 = null;
Class c3 = null;
try {
c1 = Class.forName("java.lang.Thread");
c2 = Class.forName("java.lang.String");
c3 = Class.forName("java.lang.Integer");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Note that the forName method requires that you provide the fully qualified name of the class, that is, the class's simple name preceded by the name of the package containing the class (Q1.30).
In the JDK 1.1, if you know the class's name at compile time, you can get the Class instance more directly, by means of a class literal:
/* using JDK 1.1: */
Class c1 = Thread.class;
Class c2 = String.class;
Class c3 = Integer.class;
Alternatively, if you have an object and want to get at its corresponding Class instance, you can invoke the getClass method on the object. For example:
Class c4 = "a string".getClass();
Finally, what about accessing the Class instance for the class of the currently executing method? If the method is an instance method, there is a simple, general way to get the Class object-use the ever-present this field, which refers to the object the method was invoked on:
/* works inside an instance method: */
Class thisClass = this.getClass();
Even simpler, you can take advantage of the fact that this can be left implicit:
Class thisClass = getClass(); // same as this.getClass()
Class methods, however, have no notion of a current instance (no this), so you must manually provide an instance (or the class's name) before you can fetch the Class instance. This requirement, unfortunately, often forces the cart before the horse.
|
|
Q . Can I write a method that delivers dynamically (at run time) all public methods of an object?
|
Ans
:
Don't write this
yourself; use the getMethods method in class Class,
available in the JDK 1.1.
The JDK 1.1
enhances the ability of class Class to inspect Java
classes at run time, by means of classes in the java.lang.reflect
package:
Method:
instances of this class let you inspect and manipulate a
specific method of a class.
Field:
instances of this class let you inspect and manipulate a
specific field of a class.
Constructor:
instances of this class let you inspect and manipulate a
specific constructor of a class.
Following are
several of the new (1.1) methods in class Class:
getMethods():
returns an array of Method objects corresponding
to the public methods of this class.
getFields():
returns an array of Field objects corresponding
to the public fields (variables) of this class.
getConstructors():
returns an array of Constructor objects
corresponding to the public constructors of this class.
Thus,
inspecting methods, fields, or constructors at run time requires
that you obtain the Class instance for the class
you're interested in, then invoke the appropriate accessor
methods. The following example method takes an object argument and
prints out all the accessible methods, fields, and constructors in
the class of that object:
public static void printClassInfo(Object obj) {
Class c = obj.getClass();
Method[] methods = c.getMethods();
Field[] fields = c.getFields();
Constructor[] constructors = c.getConstructors();
System.out.println("\nMethods:");
for (int i = 0; i < methods.length; ++i) {
System.out.println(" " + methods[i]);
}
System.out.println("\nFields:");
for (int i = 0; i < fields.length; ++i) {
System.out.println(" " + fields[i]);
}
System.out.println("\nConstructors:");
for (int i = 0; i < constructors.length; ++i) {
System.out.println(" " + constructors[i]);
}
}
Note: The getMethods
method returns all public methods belonging to a class-the methods
declared by the class together with the methods inherited from
superclasses.
|
|
Q .
Can I invoke methods dynamically, from names (String instances) that are determined at run time?
|
Ans
:
Yes; the
reflection API in the JDK 1.1 lets you invoke methods by means of
run-time strings representing method names, but use of this
facility is not recommended as a general design strategy.
Starting
in the JDK 1.1, the Class class and the new java.lang.reflect
package expand your ability to inspect and manipulate classes and
methods at run time. The reflection API also lets you pull out
individual elements from a class or class instance and act on
them. You can:
- invoke a method
by means of a
Method instance fetched at run time
(using Method's invoke method)
- change the value
of a field by means of a
Field instance fetched
at run time (using one of Field's set... methods)
- create a new
class instance by means of a
Constructor object
fetched at run time (using Constructor's newInstance
method)
These capabilities
are essential for component integration frameworks, such as
JavaBeans™, and for application builder tools.
Let's focus now on methods. Invoking
a method dynamically requires two basic steps:
- Obtain a
Method
instance using Class's getMethod
method.
- Invoke the
invoke method on that
Method instance.
(The English
description is almost comical here because of the multiple levels
of reference to object-oriented constructs.) As an example of step
1, the following code obtains a Method instance
representing the substring(int, int) method in class String:
/* Get Method instance representing String.substring(int, int). */
Class theClass = String.class;
Class[] parameters = {int.class, int.class};
Method theMethod = null;
try {
theMethod = theClass.getMethod("substring", parameters);
} catch (NoSuchMethodException e) {
// ... handle exception
}
A
significant restriction in using getMethod is that getMethod
requires a Class object to represent each method
parameter. If the parameter is already of a class or interface
type, this step is straightforward. However, if the method
parameter has a primitive data type, such as int or double,
you need to provide an instance of class Class
specially designed to represent that primitive type. Table 2.6
lists the Class objects and corresponding class
literals (introduced in the JDK 1.1) that you can use to represent
the primitive types.
Table 2.6:Class
Instances and Class Literals for the Primitive Types
| Primitive
type |
Class
instance |
Class
literal |
double |
Double.TYPE |
double.class |
| float |
Float.TYPE |
float.class |
long |
Long.TYPE |
long.class |
| int |
Integer.TYPE |
int.class |
short |
Short.TYPE |
short.class |
byte |
Byte.TYPE |
byte.class |
| char |
Character.TYPE |
char.class |
boolean |
Boolean.TYPE |
boolean.class |
void |
Void.TYPE |
void.class |
Note that void,
strictly speaking, is not a type, but it still needs a Class
instance representing it for use with the java.lang.reflect
classes.
Once you obtain the Method
instance, you can invoke the invoke method on it.
Just as getMethod requires an array of Class
instances to represent the parameter types, Method's invoke
method requires an array of Object instances to
represent the actual arguments to the method when you invoke it.
If a method argument is a primitive data type, you must use one of
the wrapper classes in the java.lang package, such as
Integer or Double, to place the argument
value inside an appropriate class instance:
/* Execute "123".substring(1, 2). */
Object[] arguments = {new Integer(1), new Integer(2)};
String s1 = null;
try {
s1 = (String) method.invoke("123", arguments);
} catch (InvocationTargetException e) {
// ... handle exception
} catch (IllegalArgumentException e) {
// ... handle exception
}
These
examples also illustrate the kinds of exceptions that the
methods can throw: getMethods can throw NoSuchMethodException,
and invoke can throw InvocationTargetException
and IllegalArgumentException.
Invoking methods dynamically from
string names is an important piece of flexibility in the Java
system. However, this capability circumvents Java's many built-in
mechanisms for compile-time name checking and type checking-it
should be used sparingly and with caution.
|
|
Q . How can I accomplish the equivalent of function pointers in Java, for instance, for use in an array?
|
Ans
:
To treat
executable code as an assignable, run-time swappable unit, you
need to package it in a (small) class; the inner class facility
added to the Java language starting with the JDK 1.1 simplifies
this work.
In
the Java language, the smallest unit of code that you can treat in
an object-like fashion is the class. ("The quanta of behavior
are classes," is James Gosling's terser version of this
idea.)
To encapsulate code so that you can
assign it to variables, pass it from object to object, and so on,
you need to create one or more classes to contain the code. You
can use either an interface or a simple superclass as the type for
the code objects you want to manipulate. The following sample code
shows one simple way to accomplish this, within the JDK 1.0.2 Java
language:
interface DoIt {
public void doIt();
}
class PrintMonth implements DoIt {
public void doIt() {
String[] monthNames = {"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December"
};
int monthIndex = new java.util.Date().getMonth();
System.out.println(monthNames[monthIndex]);
}
}
class PrintDay implements DoIt {
public void doIt() {
String[] dayNames = {"Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday",
"Friday", "Saturday"};
int dayIndex = new java.util.Date().getDay();
System.out.println(dayNames[dayIndex]);
}
}
class Demonstration_1_0_2 {
public static void main(String[] args) {
DoIt[] thingsToDo = {new PrintMonth(), new PrintDay()};
for (int i = 0; i < thingsToDo.length; ++i) {
thingsToDo[i].doIt();
}
}
}
The
JDK 1.1 release augments the Java language with the notion of inner
classes: classes and interfaces that can be declared as
members of another class. Inner classes, especially anonymous
inner classes, make it significantly easier to define small
classes
|
|
Q . How do I get
multiple return values back from a method?
|
Ans
:
You can just have the
function return a Vector. This is particularly convenient when
you're not sure how much you are going to be returning, based on
what occurs in the method. A Vector is essentially a dynamically-growable
array. Regular arrays can't grow after you declare them - you have
to declare a bigger array and move the old stuff into it.
|
|
|
|