Java Cert Notes

    • Unchecked Exceptions are literally those not checked by compiler to force a catch/rethrow. In effect it's all those inherites from RuntimeException class.
    • for loop: init-bool-body-update-bool-body-update-...-bool-QUIT
    • Only compiler error if lose precision e.g. int a = 3.14
    • Variable declaration or declaration + assignment (e.g. int a = 1; int a = getInt();) are not statement (i.e. to be used in control flows as block). E.g.if (true) int a = 2; // INVALID. But just use {} to convert to a statement: if (true) { int a = 2; } // VALID
    • ++i i++ same as C
    • The signature of the main method: public static void main(String[] foobar) or public static void main(String... barfoo). And it can also be a final.
    • The mythical do-while: do while (true) {} while(true); is not so mythical after all! It's nested do-while + while!
    • This is wrong: TwoLoops() { super(); this(1); } because call to this must be the first statement (so exclusive with super())
    • super.getClass().toString will be subclass name. Why? Because anyway you are invoking the implementation on Object. If not overriden, this.method() and super.method() exactly the same.
    • No overriding with diff return types. Basically return type is not considered part of method signature
    • Type arr[] and Type[] arr are allowed
    • Assignment operator is even slower Boolean operators
    • When concat with String, will auto call toString on types or convert primitives
    • You can have underscores in between numeric literals. you cannot place underscores in the following places: At the beginning or end of a number; Adjacent to a decimal point in a floating point literal; Prior to an F or L suffix; In positions where a string of digits is expected
    • Use vertical bar to separate exception types: catch (Exception1 | Exception2 e)
    • Only the '+' operator performs implicit conversion to a String object.
    • If static import has collisions, compiler will complain (e.g. Long.MAX_VALUE and Integer.MAX_VALUE)
      Modifier Class Package Subclass World
      public Y Y Y Y
      protected Y Y Y N
      no modifier Y Y N N
      private Y N N N
    • If protected static method/attribute, subclass is able to access by SuperName.methodName. If protected non-static, subclass can't access the staightforward way: A a = new A(); a.test // Visibility error. Have to inherit and manifest from Subclass. It can be inherited further, but can't be accessed from other classes in the same package of Subclass.
    • Even class has no abstract method, if class prefixed with abstract, it can't be instantiated.
    • Can't have private abstract because subclass can't see and can't override
    • Constructor can't have non-access modifiers
    • This works as compiler is smart to auto-narrow: byte a = 'a'; short b = 'b'; but not short bc = '\uff12'; More on this: byte is 8-bit, short 16-bit, int 32-bit, long 64-bit, char 16-bit: It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive). So, it's special that char can be casted to byte. But it's because 'a' is within 8-bit therefore Java is able to do auto-lose-precision-downcast
    • Let's get the terms right: Nested Classes include Static Nested Classes and Inner Classes. Inner Classes can't have static things unless it's a static final constant field.
    • An identifier can start with a doller sign, underscore, letter even Unicode letter, but not special symbols. It can continue with doller sign, underscore, letter even Unicode letter, numbers. Unicode symbols are not allowed.
    • java.lang is autoimported. Other all not autoimported. Importing import static package.A.* doesn't make A available as a class
    • Default visibility can be inherited by Sub in the same package
    • You can overload any method which might also come from parent. You can't have only-return-type-different methods anywhere, unless the parent one is invisible. It's all about no ambiguity on the compiler level.
    • Can only open up visibility for inherited (override) methods. Can throw any unchecked exceptions, but not checked. It can narrow. It can expand in the form of unchecked because the default is "any unchecked can be thrown" anyway.
    • If you overload, you can have different return types.
    • If you pass a super reference to overloaded method name, it will invoke based on the reference type (that is, judge the type of the object so that it choose the method - not invoke on, but invoke with). It's not dynamic binding. From which class in the inheritance class is dynamic, from which among the overloaded methods is not.
    • Covariant return type: when overriding, it's allowed to return original return type's subtype
    • If want a super constructor other than the no-arg to be called, must explicitly invoke so. Even if super has only one constructor and it's not no-arg.
    • If I have a constructor for Super, it's no-arg but it's not default. In Sub do I need to call super() explicitly? No!
    • Variables are not polymorphic in Java. No runtime resolution. So based on ref variable type. I mean this. If 1 object, referred using both Super and Sub reference variables, sout(super.a) and sout(sub.a) will be different! But you can get it from parents, so it's inherited. You can also shadow it. Another intersting finding is how Java methods are different from JS. In JS, a function definition is pure and it can be attached to any this. But in Java, if it goes up to parent class, this.j will be parent's j field. That is, if it's JS, it should still use child j field, because it simply says this.j and this is child. But because method resolution has gone up, it now uses parent.j, not just the original "this".j
    • You can't declare same name variable twice, other than instance-local shadowing. So no block var scope shadow method var scope.
    • You can do arr instaceof int[]. And int[] and int[][] don't have inheritance relationship. So if dimention doesn't match, it will give compile error saying they are not in the same hierachy.
    • In Java modulo or remainder: as it should a % b = a - a / b * b; i.e. it's the remainder. Now need to understand division in Java. A division involving a negative is sign-flipped, and then the division carried out on a positive equivalent, and then the answer flipped back again. So the effect is naturally going to be round toward zero. Because the absolute value tend to be less, because it not enough to increase the quotient by 1 more when it's positive. See below.
    for (int i = -9999; i<=9999; i++) {
        for (int j = -9999; j<=9999; j++) {
            if (j == 0) continue;
            // Division
            int expected = Math.abs(i) / Math.abs(j);
            expected = i * j > 0 ? expected : -1 * expected;
            int actual = i / j;
            if (expected != actual) {
                System.out.format("ERROR: %d / %d = %d but expected %d%n", i, j, actual, expected);
            // Remainder
            expected = i - expected * j;
            actual = i % j;
            if (expected != actual) {
                System.out.format("ERROR: %d % %d = %d but expected %d%n", i, j, actual, expected);
    • For multi-dimension array initialization, the first dimension's size must be specified.
    • Ternary operator, after : can't be omitted.
    • Can't assign int[][] arr1 int[] arr2 references. Can't assign short[] int[] byte[] references. But can assign Super[] Sub[] arrSuper = arrSub, NOT arrSub = arrSuper
    • Unicode char declaration much be enclosed in single quotes. Double quotes in String works as well. That is, can do String str = "abc\u0000abc" and char c = '\u0000'.
    • For switch expr, accepts byte char short int (smaller than int), and enum, String. case expr must be a compile time constant, and can be implicitly (w/o precision loss) casted to switch expr type.
    • You can totally have case 42: {}, because it's expecting expression and we can use block.
    • Default doesn't have to be the last. It act just like any other case member. If any other case match, that case will be entry point and do fall through. If all doesn't match, then it goes to default and do fall through.
    • Strictly no duplicated values (even if it's only the same value after casting) and only 1 default case is allowed
    • Enhanced for loop, left of : has to declare new var, and can't be already defined, except for instance-local shadowing.
    • You can label any expression (i.e. not declaration) or block. Most commonly used on loop to break label; and continue label; Naming rules are same as Java variable.
    • If you have the following, Compiler will issue Unreachable statement warning
    abc: {
        int j = 6;
        do {
            break abc;
        } while (true);
    • You can have more than one same name labels. The enclosing one will take effect. If wrong label enclosing, or no label, it won't compile and showing "undefined label".
    • This won't work: for (int x = 0, int y = 1; Expr; Expr) so must for (int x = 0, y = 1; Expr; Expr)
    • Java will attempt to catch all exceptions, subject to JVM status. Examine the following. Most of the time everthing's OK will be printed.
    public static void main(String[] args) {
      try {
      } catch (Throwable e) {
        System.out.println("everything's OK");
    static void go() {
      int i = 1/0;


    • In interface: you can have fields, but it's implicit static final. You can have static methods, but must have body. Rest methods implicit public abstract.
    • abstract on Interface is not necessary but could-have
    • Interfaces themselves can be package-private or public.
    • static method allowed in interface only in Java 8. Constant and static inner class are allowed in interface. Inner interface are allowed. They become available as parent static fields if a class implemented the interface. That is, directly use.
    • To summarize: fields, must public static final; instance method, must public abstract; static method, must public static also, only allowed in Java 8, probably to allow interface to be modifed and evolve, and can't add final because static already means can't be overriden; nested class, which must be public static, that is static nested class, can be final or not which only affects if it can be subclassed; lastly interface, must public static, of course not final because it contradicts with interface.
    • When throw in one method, the subsequent statements will be marked "unreachable". But if in another method and do a call, it won't mark.
    • Try block scoping and catch finally block are separate!
    • Leading 0 means octal when integer. Ignored when float.
    • More on array polymorphism and interitance. Not ok: Object[] oa = new int[3]; because int is primitive. But inheritance all works when it's all object: Exception[] ea = new RuntimeException[3];
    • Try Catch block declarations, including the ones in parens, are subject to "no local-block shadowing" rule
    • In abstract classes, methods are not by default abstract! Must be marked as abstract if no body.
    • Constructors don't need to call "corresponding" super constructor.
    • Java default int is 32bit: 4 * 000 000 000. long 64 bit
    • Again on switch case constant requirements. Upcasting from byte short... OK. Down casting no. No auto unboxing because it's not compile time constant! It might be int yes.
    • Switch case enum is special where you can directly use the other enum values. Based on the Swtich expr type, it will resolve the rest in case expr.
Written on January 22, 2016