Showing posts with label scjp. Show all posts
Showing posts with label scjp. Show all posts

January 7, 2010

Array index behavior in Java

int indexFor1D = 3;
int indexFor2D = 1;
int [] array1D = { 5, 6, 7, 8, 9 };
int [][] array2D = {{1, 2}, {3, 4, 5}, {6, 7, 8, 9}};

System.out.println("From 2D: " + array2D[indexFor2D++][indexFor2D++]);
System.out.println("indexFor2D: " + indexFor2D);

array1D[indexFor1D++] = indexFor1D;
System.out.println("indexFor1D: " + indexFor1D);
System.out.print("New 1D: ");
for(int tmp : array1D)
System.out.print(tmp);


produces output

From 2D: 5
indexFor2D: 3
indexFor1D: 4
New 1D: 56749

Nerd Sniping or: Finally Always Wins, Unless You Crash The Machine Beforehand.

try {
return true;
} finally {
return false;
}


http://stackoverflow.com/questions/1995113/strangest-language-feature/2005435#2005435

January 6, 2010

Rules for bits in Java

All integer literals are, by default, ints in Java. All floating point literals are, by default, doubles. If a value larger than allowed is put into a given primitive type, the leftmost bits are discarded. So,

char c = (char) 65656; // Binary 00000000000000010000000001111000
byte i = (byte) 130; // Binary 00000000000000000000000010000010

A char is 16 bits, so it is set to 0000000001111000, which equals 1111000, which is 120, which in turn is the character 'z'; a byte is eight bits, so it is set to 10000010. Since the first bit is a sign bit, this actually equals -126. (By two's complement, 10000010 = -(01111101 + 1) = -(01111110) = -126.)

Division by zero in Java

Incredibly, the following code will compile without any problems:


int x = 7/0;
System.out.println(x);

int y = 0;
int z = 7/y;
System.out.println(z);


When the inevitable runtime error occurs, it appears as an ArithmeticException; there is no such thing as DivideByZeroException.

January 5, 2010

Increment and decrement for array indices in Java

This code


int anIndex = 1;
int [][] anArray = {{1, 2}, {3, 4, 5}, {6, 7, 8, 9}};
System.out.println("Number: " + anArray[anIndex++][anIndex++] + ".");


prints out "Number: 5." That's anArray[1][2]; anIndex is incremented after each index, so it ends up at 3 by the end of the code fragment.

Concatenation to strings in Java


System.out.println("" + 1 + 2);
System.out.println(1 + "" + 2);
System.out.println(1 + 2 + "");


results in

12
12
3

Class initialization in Java

"Static init blocks are executed at class loading time, instance init blocks run right after the call to super() in a constructor. When multiple init blocks of a single type occur in a class, they run in order, from the top down." -K. Sierra & B. Bates, SCJP Sun Certified Programmer for Java 6 Study Guide (Exam 310-065)

Class loading time is the same as initialization time, which is described right at the top of section 12.4 of the Java Language Specification.

What happens if more than one class contains static init blocks? Are static init blocks guaranteed to run? My question at Stack Overflow covers these questions.

What about multiple instances of a class? As expected, the static initialization blocks do NOT run again. Modifying main() from the link above to this:


System.out.println("START");
new Child();
System.out.println("MIDDLE");
new Child();
System.out.println("END");


produces this output:

START
static - grandparent
static - parent
static - child
instance - grandparent
constructor - grandparent
instance - parent
constructor - parent
instance - child
constructor - child
MIDDLE
instance - grandparent
constructor - grandparent
instance - parent
constructor - parent
instance - child
constructor - child
END

Initialization blocks in Java

Code:

public class LoadTest
{
public static void main(String[] args)
{
System.out.println("START");
new Child();
System.out.println("END");
}
}

class Parent extends Grandparent {
// Instance init block
{
System.out.println("instance - parent");
}

// Constructor
public Parent() {
System.out.println("constructor - parent");
}

// Static init block
static {
System.out.println("static - parent");
}
}

class Grandparent {
// Static init block
static {
System.out.println("static - grandparent");
}

// Instance init block
{
System.out.println("instance - grandparent");
}

// Constructor
public Grandparent() {
System.out.println("constructor - grandparent");
}
}

class Child extends Parent {
// Constructor
public Child() {
System.out.println("constructor - child");
}

// Static init block
static {
System.out.println("static - child");
}

// Instance init block
{
System.out.println("instance - child");
}
}


Output:
START
static - grandparent
static - parent
static - child
instance - grandparent
constructor - grandparent
instance - parent
constructor - parent
instance - child
constructor - child
END

Generic methods in Java


public static void main(String[] args) {
genericMethod("abc");
}

static void overloadedMethod(Object o) {
System.out.println("overloadedMethod(Object) called");
}

static void overloadedMethod(String s) {
System.out.println("overloadedMethod(String) called");
}

static void overloadedMethod(Integer i) {
System.out.println("overloadedMethod(Integer) called");
}

static <T> void genericMethod(T t) {
overloadedMethod(t);
}


produces output "overloadedMethod(Object) called"; this is because the generic method doesn't know what kind of argument will be passed in at compile time [DBL-CHECK REASON]

Characters in Java

A char in Java is technically just an unsigned 16-bit number. The following code works just fine...


// 65656 - 1 - 120 = 65535, the max 16-bit unsigned range
char crazyChar = (char) 65656;
System.out.println("(char) 65656: " + crazyChar);


... and produces output "(char) 65656: x" (the ASCII/Unicode value for x is 120).

This is also perfectly legal, if not meaningful:

char crazierChar = (char) -552;

Note that casts are required for both of these snippets.

Default initialization in Java

In Java, class variables get initialized to default values. This code...

public class Test {
private static String _string;
private static byte _byte;
private static short _short;
private static int _int;
private static long _long;
private static float _float;
private static double _double;
private static boolean _boolean;
private static char _char;

public static void main(String[] args) {
System.out.println("str " + _string);
System.out.println("byt " + _byte);
System.out.println("sht " + _short);
System.out.println("int " + _int);
System.out.println("lng " + _long);
System.out.println("flt " + _float);
System.out.println("dbl " + _double);
System.out.println("bln " + _boolean);
System.out.println("chr " + _char);
}
}


...produces this output...

str null
byt 0
sht 0
int 0
lng 0
flt 0.0
dbl 0.0
bln false
chr [the non-printable character U+0000]

Unlike class variables, method-local variables are NOT automatically initialized. This code will produce a compile-time error ("the local variable anotherInt may not have been initialized"):

int anotherInt;
System.out.println(anotherInt);


On the other hand, the compiler won't catch non-initialized class objects; this code, after the earlier snippet, compiles just fine but will cause a NullPointerException at runtime:

if ("impossible".equals(_string)) {
int x = 5;
}

December 24, 2009

Inner classes

Inner classes are the same as nested classes
Method-local inner classes
Anonymous inner classes
Static inner classes (which are the same as static nested classes) are not like "regular" inner/nested classes; they're regular classes which are static members of their containing classes, similar to a static String or static int.

FINISH THIS

Overriding vs. Overloading vs. Hiding

  • Overloading is using the same method name with a different parameter list.
  • Overriding is replacing a superclass method with a different and/or more specific one in a subclass.
  • Hiding is similar to overriding but not quite the same. In the special case where a subclass's static method has the same signature as a parent class's static method, the subclass's method hides rather than overrides the parent class's method. This makes the parent class's method completely unaccessible. TODO: Find out whether this is the only situation in which hiding applies.

Useful links
The best explanation I've found so far, from the JavaRanch FAQ

Also useful, from the Java Tutorials

This StackOverflow post is technically about .NET, but I think it's still correct for Java

Some examples from the Java Language Specification

December 22, 2009

Java generics, name clash and erasure

In progress: Adding to this post

General Overview

http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html

FILL IN fancy term

It is not legal to use List<SubtypeOfFoo> as a subtype of List<Foo>. This is counterintuitive, especially because it IS legal to treat SubtypeOfFoo[] as a subtype of Foo[]. (Aside: new Integer[] { 1, 2, 3 } instanceof Number[] returns true.) This makes sense, because it prevents the following error from occurring:

// Bicycle and Train are subclasses of Vehicle
public void foo() {
List<Bicycle> bikes = new ArrayList<Bicycle>
addVehicle(bikes);
}

public void addVehicle(List<Vehicle> vehicles) {
vehicles[0] = new Train();
}



The matching code using arrays, shown below, compiles okay but will throw an ArrayStoreException at runtime. This works for arrays but not for generified collections because type erasure (see next section) makes it impossible for the JVM to throw a generified-collection equivalent of the ArrayStoreException.


// Bicycle and Train are subclasses of Vehicle
public void foo() {
Biycle[] bikes = { new Bicycle(), new Bicycle(), new Bicycle() };
addVehicle(bikes);
}

public void addVehicle(Vehicle[] vehicles) {
vehicles[0] = new Train(); // Compiles, but will explode at runtime
}


ADD MORE INFO HERE

Type Erasure

This is basically a fancy term for "all information about generics goes away before runtime." To give slightly more detail, a modern compiler will check generics for correctness to the best of its ability and insert casts where needed. As soon as that's done, it discards — or, erases — the generics and finishes compilation. By runtime, the JVM has no idea that generics were ever used; the code looks the same as it would have before J2SE 5, when generics were introduced.

The name clash error

Remember parameters for parent classes! From http://elliottback.com/wp/name-clash-the-method-blah-has-the-same-erasure-as-type-blah-but-does-not-override-it/:

Name clash: The method [foo] of type [some generic type] has the same erasure as [foo again] of type [some other generic type] but does not override it

In some cases, this can be fixed by adding parameters to the superclass name in the class containing foo. That is, change

class Bar<T> extends SuperBar

to

class Bar<T> extends SuperBar<T>

Equality in Java

One of the few methods that comes with all Java classes is equals(). By convention, it tests for MEANINGFUL equality. Therefore, this code


Integer i1 = new Integer(5);
Integer i2 = new Integer(5);

boolean test1 = i1.equals(i2);
boolean test2 = i2.equals(i1);


should produce true for both calls.

On the other hand, the equality operator (==) tests to see whether two references actually point at the same object. It "simply looks at the bits in the variable, and they're either identical or they're not" -K. Sierra & B. Bates, SCJP Sun Certified Programmer for Java 6 Study Guide (Exam 310-065). So, the values in the previous example would be false, but this code:


Integer i1 = new Integer(5);
Integer i2 = i1;

boolean test = i1 == i2;


will produce true.

December 17, 2009

Quick-reference table of Java access modifiers

The table on this page lists the differences between public, protected, package-protected — AKA no modifier — and private fields in Java:

ModifierClassPackageSubclassWorld
publicYYYY
protectedYYYN
[no modifier]YYNN
privateYNNN


Source: http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

Terms for easy searching later:
package-private, package-protected, access control, public, protected, private

December 16, 2009

Glossary

Eventually, this should probably be expanded to a list of links to glossary sub-pages based on first letter.

cohesion - "the degree to which a class has a single-well-focused purpose" -K. Sierra & B. Bates, SCJP Sun Certified Programmer for Java 6 Study Guide (Exam 310-065)

covariance - Child[] is a subtype of Parent[] (as long as Child is a subtype of Parent). FILL IN MORE cf. contravariance, invariance Wikipedia article

contravariance - FILL IN cf. covariance, invariance Wikipedia article

invariance - List<Child> is not a subtype or a supertype of — or in any way related to, really — List<Parent> FILL IN MORE cf. covariance, contravariance Wikipedia article

non-reifiable - "[a type] whose runtime representation contains less information than its compile-time representation" -J. Bloch, Effective Java, Second Edition (all parameterized types except unbounded wildcards) FILL IN MORE

ordered - FILL IN cf. sorted

sorted - FILL IN cf. ordered

type safety - a guarantee that objects of a given type can't be treated as objects of another type, with exceptions for subclasses; Stack Overflow definition

List of special topics

strictfp keyword
Var-args
finalize() method
Assertions
Labeled break/labeled continue
Constant pools

Assertions in Java

Turn on assertions with the -ea or -enableassertions command line flag

In Eclipse, right-click on the file to run in Package Explorer, hover on "Run As" (or "Debug As") and select "Run Configurations..." (or "Debug Configurations..."). Then, select the "Arguments" tab and add the flag in the "VM arguments" box.

Discussion of assertions in production code from Dr. Dobbs