Received: from SOUTH-STATION-ANNEX.MIT.EDU by po10.MIT.EDU (5.61/4.7) id AA27805; Tue, 11 Jan 00 16:05:16 EST
Received: from hermes.javasoft.com by MIT.EDU with SMTP
	id AA08449; Tue, 11 Jan 00 16:04:48 EST
Received: (from nobody@localhost)
	by hermes.java.sun.com (8.9.3+Sun/8.9.1) id VAA00907;
	Tue, 11 Jan 2000 21:04:37 GMT
Date: Tue, 11 Jan 2000 21:04:37 GMT
Message-Id: <200001112104.VAA00907@hermes.java.sun.com>
X-Authentication-Warning: hermes.java.sun.com: Processed from queue /bulkmail/data/ed_27/mqueue7
X-Mailing: 195
From: JDCTechTips@sun.com
Subject: JDC Tech Tips  January 11, 2000
To: JDCMember@sun.com
Reply-To: JDCTechTips@sun.com
Errors-To: bounced_mail@hermes.java.sun.com
Precedence: junk
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
X-Mailer: Beyond Email 2.2


 J  D  C    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips, 
January 11, 2000. This issue covers:

         * Narrowing and Widening Conversions
         * Using Import Declarations
         
These tips were developed using Java(tm) 2 SDK, Standard Edition, 
v 1.2.2.

You can view this issue of the Tech Tips on the Web at 
http://developer.java.sun.com/developer/TechTips/2000/tt0110.html.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

NARROWING AND WIDENING CONVERSIONS

Suppose you're doing some C or C++ programming, and you have a
sequence of statements like this:

    long a;
    short b;

    a = 123456;
    b = a;

What happens?  This is probably a programmer error. Here a value
(123456) is assigned to a variable (b) that's probably
too small to represent it. (This assumes that a value of data type 
short is 16 bits). C and C++ do not prohibit this operation; the 
result is implementation-defined. An experiment with a couple of 
C++ compilers shows a value of -7616 for b.

This usage is illegal in the Java(tm) programming language, and it 
serves to illustrate the way in which the language treats 
conversions. Specifically, when you convert a larger primitive type 
(like long) to a smaller primitive type (like short), it requires 
a cast to be valid. For example: 

    b = (short)a;

Converting a large primitive type to a smaller primitive type is 
called "narrowing primitive conversion". This type of conversion
has the potential for some loss of information. That's because
all but the lowest bits of data are discarded in the conversion.
In this example, the lowest 16 bits are saved, because a short is
guaranteed to have exactly 16 bits. By dropping the higher bits of 
data, you might lose information about the magnitude and precision 
of the original value. The magnitude is the range of values that a 
primitive type can represent. For example, if you convert a long to 
a byte, you'll probably lose magnitude information, because a long 
can represent a much wider range of values using 64 bits than a 
byte can using 8 bits. 

The idea of precision can be illustrated using float and double. 
You can represent a value like "pi" with more significant digits 
if you use a double instead of a float.

In addition to a loss of magnitude and precision, the sign of the 
converted value can be different than the sign of the original 
value.

Widening conversions are analogous to narrowing conversions. A
widening conversion never loses information about magnitude, but can
lose precision. For example, if you convert a long to a float, you
might sacrifice precision. A float has 32 bits instead of 64,
and uses some of those bits for an exponent. So a float cannot
represent all 64 bits of the long value. A float can represent the
magnitude of a long, but not necessarily the precision. No cast is
required for a widening conversion such as:

    long a;
    float f;

    a = 1234567890;
    f = a;

Narrowing and widening primitive conversions never result in a
run-time exception, even in cases where information is lost.

There's a special case known as an "assignment conversion" that
handles some conversion cases that would otherwise seem to be
illegal, such as:

    byte x;

    x = 59;

In this example, a variable of type byte is being assigned a value
of type int. This implies a narrowing conversion. And it's legal
if (a) the expression to be assigned (59) is of constant int type, 
(b) it's being assigned to a variable (x) of type byte, short, or 
char, and (c) it will fit into the variable without losing any 
information. In other words, you can assign small integer constants 
to byte, char, and short variables without worrying about using a
cast.

Narrowing and widening conversions also apply to reference types. 
For example, if you have:

    class A {}
    class B extends A {}

    ...

    A aref = new A();
    B bref = new B();

then usage like:

    aref = bref;

is a widening conversion, and usage such as:

    bref = (B)aref;

is a narrowing conversion. Widening reference conversions never
throw a run-time exception, but narrowing reference conversions 
can throw a ClassCastException for usage like this:

    class A {}
    class B extends A {}
    class C extends A {}

    ...

    B bref = new B();
    A aref = bref;
    C cref = (C)aref;

The variable "aref" references a B, not a C, and an attempt to 
force the B into a C results in an exception.

USING IMPORT DECLARATIONS

If you've done any amount of Java programming, you've likely used 
import declarations, of the form:

    import java.util.*;

or:

    import java.util.ArrayList;

These are quite simple in a way, but there are a couple of
interesting issues to mention concerning the use of these
declarations.

The first point is that an import declaration makes a type or 
set of types available, but doesn't do any textual inclusion 
of files. By contrast, the C #include directive actually 
substitutes text into the including file. So that:

    #include <stdio.h>

actually results in a header file "stdio.h" being inserted into 
the compilation unit. In Java programming, a corresponding 
declaration:

    import java.util.ArrayList;

simply says that the class type ArrayList can be used in the 
program without full qualification (that is, "ArrayList" instead 
of "java.util.ArrayList").

There's an implicit import declaration:

    import java.lang.*;

assumed at the beginning of a Java compilation unit, just
after any package statement in the unit. A wildcard like "*" says
"make available all public types from the package", in this case,
all types in the package "java.lang". Wildcards are never used to
import subpackages, so an import like:

    import java.lang.*;

doesn't give you access to the classes in java.lang.reflect, a
subpackage of java.lang. You need to say:

    import java.lang.reflect.*;

to access those classes.

What about ambiguities?  What if you import two types with the 
same name from different packages?

    import P1.A;
    import P2.A;

This is invalid usage. However, what if you say instead:

    import P1.*;
    import P2.*;

and both packages P1 and P2 contain an A type?  Well, if you don't
actually use the A in your program, then it's okay. But if you say:

    A a = new A();

you'll get an ambiguity error. In other words, you get an error
if (a) you use a type-import-on-demand declaration (that is, an 
import declaration using a wildcard), (b) two different packages 
have types with the same name, (c) you use that type. There is no
rule that says "the first one wins".

There are a couple of different styles you can use with imports. 
Suppose you need to use ArrayList and Vector from java.util. 
You can say:

    import java.util.*;

or:

    import java.util.ArrayList;
    import java.util.Vector;

These are both "right". The first is terse; you don't have to
enumerate all the types you're using. The second makes clear 
what types you're using in your program, at the expense of some 
verboseness. The second approach also has a subtle advantage in 
that it forces a type to be found in a particular package. Here's 
an example. Suppose you want to use a type A, and you say:

    import P1.*;
    import P2.*;

And you believe that A is found in P1, when it's actually not in P1
but in P2. Explicitly enumerating the types you're using gets
around this problem. If you think A is in P1, and you say:

    import P1.A;

and it's not actually there, you'll get a compile error.

Is there any efficiency issue between these two styles?  Possibly,
but since import declarations don't actually import anything into
your program, any difference is very small. Remember that there's
an implicit "import java.lang.*" at the top of your compilation
units, and java.lang in JDK(tm) 1.2.2 contains 75 classes and
interfaces. An experiment using a contrived example, one with
thousands of class name uses that must be looked up, showed a
negligible change in compilation speed. So compilation 
performance should probably not be considered a factor when 
choosing one format over another.

There's one final angle of interest on import declarations.
Suppose you use an inner class:

    package P;

    public class A {
        public static class B {}
    }

If you want to access A from another compilation unit, you say:

    import P.*;

or:

    import P.A;

But if you'd like to access B without qualification, you need to
say:

    import P.A.*;

or:

    import P.A.B;

The first of these makes available types within the class A found 
in package P. The second makes available just the type B found in
class A in package P.




.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

- NOTE
The names on the JDC mailing list are used for internal Sun
Microsystems(tm) purposes only.  To remove your name from the list,
see Subscribe/Unsubscribe below.


- FEEDBACK
Comments?  Send your feedback on the JDC Tech Tips to:

jdc-webmaster@sun.com


- SUBSCRIBE/UNSUBSCRIBE
The JDC Tech Tips are sent to you because you elected to subscribe
when you registered as a JDC member.  To unsubscribe from JDC Email,
go to the following address and enter the email address you wish to
remove from the mailing list:

http://developer.java.sun.com/unsubscribe.html


To become a JDC member and subscribe to this newsletter go to:

http://java.sun.com/jdc/


- ARCHIVES
You'll find the JDC Tech Tips archives at:

http://developer.java.sun.com/developer/TechTips/index.html


- COPYRIGHT
Copyright 1999 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This document is protected by copyright.  For more information, see:

http://developer.java.sun.com/developer/copyright.html


This issue of the JDC Tech Tips is written by Glen McCluskey.

JDC Tech Tips 
January 11, 2000












