Casting is the conversion of one data type into another.
Generally, casting to a smaller type that would lose data is considered an unsafe cast. This would have to be done explicitly by the programmer. If you can't ensure that the data type you're casting to can accept the value, that's not ideal.
Casting to a larger type (e.g. int -> long
) is done implicitly.
A private field is accessible only to its own class, whilst a protected fied is accessible also to classes in the same package, and subclasses of its class in different packages.
A static method in a class can be called without an instantiated object using just the class name, whilst a non-static method must be called with/on an object of that class. A static method can only access static members of the class, whilst a non-static method can access both.
An Interface is the most abstracted, it can only have abstract methods, can only have final and static variables, and do not provide implementation of methods. An Abstract Class can have method implementations, non-final, non-static variables, and all other stuff a class can do.
Overriding means having two methods with the same name and parameters, one in the parent class, one in the child class. The child class method implementation overrides the parent class.
class Dog {
public void bark() {
System.out.println("woof")
}
}
class BigDog extends Dog {
public void bark() {
System.out.println("woof but louder")
}
}
Overloading means having two methods in the same class with the same name, but different parameters. Either can be used depending on the method signature called.
public int max(int a, int b) {...}
public double max(double a, double b) {...}
"Generics have been added to Java quite recently;" says the paper from only one or two years ago, forgetting that generics was added in 2004.
Generics are a way of typing data structures that could store any type. You'd see this as something like ArrayList<T>
, or something similar. ArrayList here could store any type of object, but the "generic type" is replaced upon instantiation with a specified data type.
This ensures type safety, so you don't accidentally store a string inside of an integer list and then crash when you try to cast back (because that list is storing Object
types).
Boolean operators, || &&
have lazy evaluation implemented. a || b
need only a
to be true, for the whole expression to be true, without evaluating b
. Similarly, a && b
need only a
to be false for the whole expression to be false.