// Examples from "The Java Programming Language", 3rd edition import java.util.*; import java.io.*; //---------- // 5.2.2: Extending inner classes class Outer { public int x; class Inner { Inner() { x = 1; } } } // Normal case: extend both Outer and Inner class ExtendedOuter extends Outer { class ExtendedInner extends Inner {} Inner ref = new ExtendedInner(); } // Strange case: unrelated class extends Inner, must provide context class Unrelated extends Outer.Inner { Unrelated() { // In order for the superclasses' constructor to work, // it needs a reference to its enclosing scope; a reference to the // left hand side of the x.super() below is saved behind the // scenes. (new Outer()).super(); // x = 5; doesn't compile } } //---------- // 5.6.1: Interfaces can do work! interface SharedData { class Data { private int x = 0; public int getX() { return x; } public void setX(int newX) { x = newX; } } Data data = new Data(); // final by default, since this is an interface } // Another way interfaces can do work - use a static inner class. //: c08:IInterface.java // From 'Thinking in Java, 2nd ed.' by Bruce Eckel // www.BruceEckel.com. See copyright notice in CopyRight.txt. // Static inner classes inside interfaces. interface IInterface { static class Inner { int i, j, k; public Inner() {} void f() {} } } ///:~ //--------- // 6.1.1: \u0065 same as \uu0065, backslash u without four digits illegal even in comments! class Demo { public static void main(String args[]) { // multiple u's allowed to enable transforming source // code between character sets without losing distinction // between 'A' and '\u0065'; see 6.1.1 System.out.println("Is this legal: '\uuuuuuuuuuuuuuuuuuuuu0065'"); // Note: \ u processing happens very early, *before* comment or quote processing! System.out.println("Is this legal: '\u0022); } } //--------- // Arrays are subclasses of java.lang.Object! class Demo2 { public static void main(String args[]) { int bar[] = new int[10]; bar[0] = 3; System.out.println("bar[0] = " + bar[0]); // Yes, you can clone arrays. You have to cast the result. It's a shallow clone. int bletch[] = (int []) bar.clone(); System.out.println("bletch[0] = " + bletch[0]); } } //------------------------------ // Examples from "Thinking in Java", 2nd ed //--------- // this is a bit odd, considering Strings are immutable, // and finalness doesn't *really* insulate you from trouble... // I bet they really wanted 'immutable' but couldn't have it. //: c08:Parcel8.java // From 'Thinking in Java, 2nd ed.' by Bruce Eckel // www.BruceEckel.com. See copyright notice in CopyRight.txt. // An anonymous inner class that performs // initialization. A briefer version // of Parcel5.java. public class Parcel8 { // Argument must be final to use inside // anonymous inner class: public Destination dest(final String dest) { return new Destination() { private String label = dest; public String readLabel() { return label; } }; } public static void main(String[] args) { Parcel8 p = new Parcel8(); Destination d = p.dest("Tanzania"); } } ///:~ //--------- // p. 476: Comparator or Comparable: comparing two int's is best done with // if, not by subtracting their value... otherwise you can have overflow. // (Not unique to java.) //--------- // If an exception happens while processing another exception, // the first exception is totally lost! //: c10:LostMessage.java // From 'Thinking in Java, 2nd ed.' by Bruce Eckel // www.BruceEckel.com. See copyright notice in CopyRight.txt. // How an exception can be lost. class VeryImportantException extends Exception { public String toString() { return "A very important exception!"; } } class HoHumException extends Exception { public String toString() { return "A trivial exception"; } } public class LostMessage { void f() throws VeryImportantException { throw new VeryImportantException(); } void dispose() throws HoHumException { throw new HoHumException(); } public static void main(String[] args) throws Exception { LostMessage lm = new LostMessage(); try { lm.f(); } finally { lm.dispose(); } } } ///:~ //--------- // p. 561: constructors don't have to declare the exceptions they throw; // they can throw absolutely anything they want. class MyException extends Exception { }; class YourException extends Exception { }; class ThrowSomething { public ThrowSomething() throws MyException {}; public void blort() throws MyException {}; } public class ThrowAnything extends ThrowSomething { // constructors can add exceptions that the base class doesn't throw public ThrowAnything() throws MyException, YourException { throw new YourException(); } // but regular methods can't; following won't compile public void blort() throws MyException, YourException {}; } //------- // Contributed by x@xman.org // foo.equals(bar) is by default (foo == bar), which only returns // true if foo and bar are the same Object -- sometimes not what you expected. public class ArrayEquals { static class foo { int x; public foo(int a) { x = a; } }; public static boolean contentsAreEqual(final foo[] listA, final foo[] listB) { if (listA.length != listB.length) return false; for (int i = 0; i < listA.length; i++) if (!listA[i].equals(listB[i])) return false; return true; } public static void main(String args[]) { foo[] listA = new foo[1]; listA[0] = new foo(8); foo[] listB = new foo[listA.length]; System.arraycopy(listA, 0, listB, 0, listA.length); System.out.println("listA == listB:" + (listA == listB)); System.out.println("listA.equals(listB): " + listA.equals(listB)); System.out.println("contentsAreEqual(listA,listB): " + contentsAreEqual(listA, listB)); } } //-------- // From http://gee.cs.oswego.edu/dl/html/javaCodingStd.html /* Avoid overloading methods on argument type. (Overriding on arity is OK, as in having a one-argument version versus a two-argument version). If you need to specialize behavior according to the class of an argument, consider instead choosing a general type for the nominal argument type (often Object) and using conditionals checking instanceof. Alternatives include techniques such as double-dispatching, or often best, reformulating methods (and/or those of their arguments) to remove dependence on exact argument type. Rationale: Java method resolution is static; based on the listed types, not the actual types of argument. This is compounded in the case of non-Object types with coercion charts. In both cases, most programmers have not committed the matching rules to memory. The results can be counterintuitive; thus the source of subtle errors. For example, try to predict the output of this. Then compile and run. */ class Classifier { String identify(Object x) { return "object"; } String identify(Integer x) { return "integer"; } } class Relay { String relay(Object obj) { return (new Classifier()).identify(obj); } } public class App { public static void main(String[] args) { Relay relayer = new Relay(); Integer i = new Integer(17); System.out.println(relayer.relay(i)); } }