Java 2 SDK for Solaris Developer's Guide

Language Incompatibilities

Compilers in JDK 1.0 and 1.1 compiled some types of illegal code without producing warnings or error messages. The Java 2 SDK for Solaris compiler is more stringent in ensuring that code conforms to the JLS. The following list summarizes the types of illegal code that compiled with JDK 1.0 or 1.1 compilers but do not compile with Java 2 SDK for Solaris.

  1. Previous compilers passed some initializations of int types to long types. These are flagged as errors in Java 2 SDK for Solaris. In the following program,


    public class foo {
    	int i = 3000000000;
    	int j = 6000000000;
    }

    both the initialization to i and j are in error. Previous compilers would only report the incorrect initialization of i. The initialization of j would have overflowed silently [bug 4035346].

  2. Previous compilers allowed the implicit assignment conversion from char to byte and short for character literals that fit into 8 bits. The compiler does not allow such implicit assignment conversion in Java 2 SDK for Solaris. For example,


    byte b = 'b';

    will not pass the compiler. Use an explicit cast for such conversions [bug 4030496].


    byte b = (byte)'b';
  3. The Java 2 SDK for Solaris compiler will not pass 0xL (not a legal hex literal). Previous compilers parsed it as zero [bug 4049982].

  4. The Java 2 SDK for Solaris compiler will not pass ''' (and therefore '\u0027') (not a legal char literal) . Use '\'' instead [bug 1265387].

  5. The Java 2 SDK for Solaris compiler will not pass "\u000D" (not legal in string and char literals). The CR and LF characters (\u000A and \u000D) terminate lines, even in comments [bug 4086919]. The following code is not :


    //This comment about \u000D is not legal; it is really two lines.

    Use \r instead [bug 4063147].

  6. The Java 2 SDK for Solaris compiler will not pass the type void[] (not legal) [bug 4034979].

  7. Do not combine the abstract method modifier with private, final, native, or synchronized modifiers; it is not legal [bug 1266571].

  8. Previous compilers would pass double-assignment of final variables in some circumstances. For example, the following two samples would pass JDK 1.1-based compilers (even though both involve double-assignment of a final variable). The Java 2 SDK for Solaris compiler will not pass such assignments [bugs 4066275 and 4056774].


    public class Example1 {
    		public static void main(String[] argv) {
    			int k=0;
    			for (final int a;;) {
    				k++;
    				a=k;
    				System.out.println("a="+a);
    				if (k>3)
    					return;
    			}
    		}
    }
    
    public class Example2 {
    		final int k;
    		Example2() {
    			k = 1;
    		}
    		Example2(Object whatever) {
    			this();
    			k = 2;
    		}
    }
    static public void main(String[] args) {
    		Example2 t = new Example2(null);
    		System.out.println("k is "+ t.k);
    }
  9. You cannot reference a non-static field with an apparently static field expression of the form Classname.fieldname. Prior to Java 2 SDK for Solaris, javac silently tolerated such expressions as if they had been written this.fieldname [bug 4087127].

  10. Section 5.5 of the JLS specifies that a cast between two interface types is a compile-time error if the interfaces contain methods with the same signature but different return types. The compiler did not generate this compile-time error prior to Java 2 SDK for Solaris [bug 4028359)]. For example, the following program now generates a compile-time error:


    interface Noisy {
    		int method();
    }
    interface Quiet {
    		void method();
    }
    public class InterfaceCast {
    		public static void main(String[] args) {
    			Noisy one = null;
    			Quiet two = (Quiet) one;
    		}
    }
  11. Java 2 SDK for Solaris does not accept an assignment expression as the third subexpression of a conditional statement. For example, the Java 2 SDK for Solaris compiler throws an error in the following statement.


    myVal = condition ? x = 7 : x = 3;

    If this problem occurs in existing code, place the offending assignment expression in parentheses to compile it as in previous versions of the JDK:


    myVal = condition ? x = 7 : (x = 3);
  12. In previous releases of javac, the compiler incorrectly omitted the initialization if a field was initialized to its default value [bug 1227855)]. This behavior can lead to different semantics for programs like the following:


    abstract class Parent {
    		Parent() {
    			setI(100);
    		}
    }
    	abstract public void setI(int value);
    }
    public class InitTest extends Parent {
    		public int i = 0;
    		public void setI(int value) {
    			i = value;
    		}
    }
    	public static void main(String[] args) {
    		InitTest test = new InitTest();
    		System.out.println(test.i);
    }

    This program produces incorrect output (100) when compiled with earlier versions of javac. The Java 2 SDK for Solaris javac produces the correct output (0).

    Single class examples can be formulated as well:


    public class InitTest2 {
    		public int j = method();
    		public int i = 0;
    		public int method() {
    			i = 100;
    			return 200;
    		}
    }
    public static void main(String[] args) {
    		InitTest2 test = new InitTest2();
    		System.out.println(test.i);
    }

    Before, the output was 100. Now it is 0. The same phenomenon can occur in programs using reference types and null.

  13. Concerning accessibility in qualified names, JLS 6.6.1 states the following:

    A member (field or method) of a reference (class, interface, or array) type or a constructor of a class type is accessible only if the type is accessible and the member or constructor is declared to permit access."

    Prior to Java 2 SDK for Solaris, the compiler did not enforce this rule correctly. It granted access if the member or constructor was declared to permit access without regard to the accessibility of the type to which it belonged as in the following illegal program.


    import pack1.P1;
    public class CMain {
    		public static void main(String[] args) {
    			P1 p1 = new P1();
    // The accesses to field 'i' below are
    // illegal, as the type of 'p2', the
    // class type 'pack1.P2', is not accessible.
    			p1.p2.i = 3;
    			System.out.println(p1.p2.i);
    		}
    }
    package pack1;
    public class P1 {
    		public P2 p2 = new P2();
    }
    // Note the absence of an access modifier, making
    // 'P2' accessible only from within package 'pack1'.
    public class P2 {
    		public int i = 0;
    }

    With the introduction of inner classes in Java 2 SDK for Solaris, a member of a class or interface might be another class or interface, as well as a field or method. Java 2 SDK for Solaris enforces the accessibility rules described to inner classes as well.

  14. Prior to Java 2 SDK for Solaris, the compiler failed to detect that certain classes were abstract. This happened when a subclass declared a method with the same name as an abstract, package-private method defined in a superclass from a different package. No overriding occurs even though the methods have the same name. As an example, compiling these files:


    package one;
    public abstract class Parent {
    		abstract void method();
    }
    
    package two;
    public class Child extends one.Parent {
    	void method() {}
    }

    yields the error message:


    two/Child.java:3: class two.Child is not able to provide an
    implementation for the method void method() declared in class
    one.Parent because it is private to another package. class
    two.Child must be declared abstract.
    	public class Child extends one.Parent {
    			^
  15. The Java 2 SDK for Solaris compiler properly detects duplicate, nested labels. These are disallowed by the JLS (the following example statement is illegal).


    sameName:
    while (condition) {
    	sameName:
    	while (condition2) {
    		break sameName;
    	}
    }
  16. The Java 2 SDK for Solaris compiler properly detects a labeled declaration. These declarations are disallowed by the JLS. This is a fix for bug 4039843.

  17. The Java 2 SDK for Solaris compiler recognizes a new keyword, strictfp, so programs can no longer use strictfp as an identifier. The Java 2 SDK for Solaris compiler uses the new keyword to set a modifier bit in the method data structures. The platform specification previous to Java 2 SDK for Solaris required that this bit be zeroed. Code written using the new keyword executes in strict floating-point mode (the default defined for the Java platform). Code that does not use the new keyword executes in default floating-point mode. This enables implementations to make better use of some processors to deliver higher performance.

    Some numeric code not marked with the strictfp keyword might behave differently in Java 2 SDK for Solaris than in previous versions. Such code might also behave differently depending on the implementation of the Java platform. Overflow or underflow can occur in different circumstances and create slightly different results. These differences are not expected to have an impact on most numeric code. However, code that is vulnerable to floating-point behavior might be affected.

  18. JDK 1.1 extended the syntax of expressions to allow a class name to qualify a reference to a current instance using the keyword this (as in the following example).


    PrimaryNoNewArray: ...
                    ClassName . this

    The value of such an expression is a reference to the current instance of the enclosing class (ClassName), which must exist.

    Prior to Java 2 SDK for Solaris, the javac compiler treated such expressions incorrectly. It produced a reference to the current instance of the innermost enclosing class that was a subtype of the type named by ClassName. The compiler now implements such expressions properly.

  19. JDK 1.1, extended the syntax of expressions allowing a class name to qualify a reference to a current instance using the keyword this (as in the following example).


    PrimaryNoNewArray: ...
                    ClassName . this

    This syntax allows access to members using constructions such as:


    ClassName.this.fieldname
    ClassName.this.methodname( ... ) 

    The presence of inner classes made this extension necessary because more than one current instance might occur at a given point in the program. The inner classes specification neglected to include a similar extension for the super keyword (as in the following example).


    FieldAccess: ...
                    ClassName.super.Identifier
    MethodInvocation:...
                    ClassName.super.Identifier(ArgumentList_opt) 

    Java 2 SDK for Solaris implements these constructs in anticipation of their inclusion in the forthcoming second edition of the JLS.

    In each case, the current instance is the current instance of the enclosing class (ClassName), which must exist.

    The following example shows how the need for the qualified super notation might arise in practice.


    class C {
    		void f() { ... }
    }
    class D extends C {
    		void f() {
                // overrides f() to run it in a new thread
    			new Thread(new Runnable() {
    				public void run() {
    					D.super.f();
    				}
    			}).start();
    		}
    }

    Implementation Note: If you need to use an access method, it must reside in the class named by ClassName, not in its superclass. The superclass does not have to be defined in the same compilation unit, and can have been compiled previously.

  20. JDK 1.1 extended the syntax of expressions allowing a constructor invocation using the keyword super to be qualified with a reference to an outer instance (as in the following example).


    ExplicitConstructorInvocation: ...
    	Primary.super(ArgumentList_opt); 

    The corresponding case for constructor invocations using this was inadvertently omitted:


    ExplicitConstructorInvocation: ...
    	Primary.this(ArgumentList_opt); 

    Java 2 SDK for Solaris implements the construct in anticipation of its inclusion in the forthcoming second edition of the JLS.

  21. The Inner Classes specification does not permit an inner class to declare a member interface. This rule is enforced in Java 2 SDK for Solaris, but such declarations are silently tolerated in JDK 1.1-based releases. For example, the following program is incorrectly accepted by javac in JDK 1.1-based releases, but is rejected in Java 2 SDK for Solaris.


    class InnerInterface {
    		class Inner {
    			interface A { }
    		}
    }

    A static member class is not an inner class; it is a top-level class (as that term is defined by the Inner Classes specification). The javac in both JDK 1.1-based releases and Java 2 SDK for Solaris accepts the following program as correct.


    class NestedInterface {
    		static class Inner {
    			interface A { }
    		}
    }

    A local class is never a top-level class, so the following example is also illegal; both javac JDK 1.1-based releases and Java 2 SDK for Solaris report a syntax error.


    class LocalNestedInterface {
    	void foo()
    			 static class Inner {
    			 	interface A { }
    			}
    	}
    }
  22. The Java 2 SDK for Solaris compiler strongly enforces the restriction that a package cannot contain a type and a subpackage of the same name. This change makes it illegal to compile a class whose fully qualified name was the same as the fully qualified name of a package on the classpath. This change also makes it illegal to compile a class whose package (or some proper prefix) would have the same name as an existing class. This is a fix for bug 4101529. The following are some examples of classes that now fail to compile:


    \\Example 1
    package java.lang.String;
    class Illegal {
    }
    
    \\Example 2
    package java;
    class util {
    }