Notes for CS4 game course
Please consider contributing
If you don't want a method to be overridden.
public final void doSomething(){
}
If you don't want a class to be inherited, you can use the final modifier too.
public final class Hello{
...
}
refrence type is the type written before equal and object type is the type we call constructor from it
public class A {
char x = 'A';
public void run {
System.out.println("Object type is A");
}
}
public class B extends A {
char x = 'B'
public void run {
System.out.println("Object type is B");
}
}
A a = new A ();
B b = new B ();
A trick = new B();
System.out.println(a.x);
System.out.println(b.x);
System.out.println(trick.x);
System.out.println("------");
a.run();
b.run();
trick.run();
Results are
A
B
A
------
Object type is A
Object type is B
Object type is B
conclusion
late binding does not apply to instance variable but apply to instance methods
Please Note:
late binding can be applied to static variables.
You can extend (only one class) and then implement (any number of interfaces). Respectively. Java doesn't have multiple inheritance
public class A {
char x = 'A';
public void run() {
System.out.println("runA");
}
public void run2() {
System.out.println("run2A");
}
}
public class B extends A {
char x = 'B';
public void run() {
System.out.println("runB");
}
public void run3() {
System.out.println("run3B");
}
}
public static void main(String[] args) {
A trick = new B();
// Code block inserted here
}
trick.run();
trick.run2();
trick.run3();
runB
run2A
// compile error
cannot find symbol
symbol: method run3()
location: variable trick of type Main.A
public class Animal {
public void run (){
System.out.println ("can have 2 or 4 legs");
}
}
public class FourLegsAnimal extends Animal {
public void run (){
System.out.println("actually has 4 legs");
}
}
public class Dog extends FourLegsAnimal{
public void run (){
System.out.println("It's a dog");
}
}
what would be the output of
Animal d = new Dog ();
d.run();
((Animal) d).run();
((FourLegsAnimal) d).run();
Output is It's a dog
It's a dog
It's a dog
conclusion
type cast does not affect method calls (it will be called from object type class)
What about
Animal a = new FourLegsAnimal();
((Dog) a).run();
it will give a run time error cannot cast from FourLegsAnimal to Dog
Note
you can not type cast to lower class (sub class) (important
lower Class means lower class of object type).
let's Add
public class TwoLegsAnimal extends Animal {
public void run (){
System.out.println("actually has 2 legs");
}
}
The OutputOf
FourLegsAnimal a1 = new FourLegsAnimal();
Animal a2 = new FourLegsAnimal();
((TowLegsAnimal) a1).run();
((TowLegsAnimal) a2).run();
Compile error
RunTime Error
impportant
you cannot type cast 2 classes in different branches , compile error depend on referenceType but runTimeErroe depends on ObjectType
You can extend (only one class) and then implement (any number of interfaces). Respectively. Java doesn't have multiple inheritance
Person p = new Person();
Student s = new Student(); // Student extends Person
Teacher t = new Teacher(); // Teacher extends Person
Person ps = new Student();
Person pt = new Teacher();
Student sp = new Person(); // compilation error
Student st = new Teacher(); // compilation error
Teacher tp = new Person(); // compilation error
Teacher ts = new Student(); // compilation error
System.out.println((Student) p); // run time error
System.out.println((Teacher) p); // run time error
System.out.println((Person) s);
System.out.println((Teacher) s); // compilation error
System.out.println((Person) t);
System.out.println((Student) t); // compilation error
System.out.println((Person) ps);
System.out.println((Student) ps);
System.out.println((Teacher) ps); // run time error
System.out.println((Person) pt);
System.out.println((Student) pt); // run time error
System.out.println((Teacher) pt);
What is the OUTPUT of the following CODE
public class Parent{
public void c1(){
System.out.print("1");
c2();
}
public void c2(){
System.out.print("2");
}
}
public class Child extends Parent{
public void c1(){
super.c1();
System.out.print("3");
}
public void c2(){
super.c2();
System.out.print("4");
}
public static void main(String [] args){
Parent p = new Child();
p.c1();
}
}
OUTPUT: 1243
In inheritance, you inherit all the public and private instance variables, but you can only access the public ones.
Look at the following Example and give the output of the 4 print statements:
public class Person {
static int counter = 0; // what if this was private?
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
counter++;
}
public static void main(String [] args) {
Person p1 = new Person("Salah",19);
Student1 s1 = new Student1("Sayed", 24);
Student2 s2 = new Student2("Samir", 28);
Student3 s3 = new Student3("Sameh", 31);
System.out.println(Person.counter);
System.out.println(Student1.counter);
System.out.println(Student2.counter);
System.out.println(Student3.counter);
}
}
public class Student1 extends Person {
public Student1(String name, int age) {
super(name, age);
}
}
public class Student2 extends Person {
static int counter = 0;
public Student2(String name, int age) {
super(name, age);
}
}
public class Student3 extends Person {
static int counter=0;
public Student3(String name, int age) {
super(name, age);
counter++;
}
}
Result:
4 // Each created object (Person or any student) incremented the static counter variable in Person
4 // Student1 inherits the same static counter variable in Person
0 // Student2 overrides the static counter variable in Person and starts from 0, the increment in the super class is reflected only in the super class' static variable
1 // Student3 overrides the static counter variable in Person but increments its new overriden static counter
The following code will not compile the NullPointerException catch block is unreachable because NullPointerException is a subClass of Exception
public void method(){
try{
//Something
} catch (Exception e){
//Something
} catch (NullPointerException e) {
//Something
}
}
While the following code will compile and run since because the compiler can't see that the second catch block is unreachable
public void method(){
try{
//Something
} catch (Exception e){
//Something
}
}
public void methodCaller(){
try{
method()
} catch (NullPointerException e){
//Something
}
}
Exceptions can only be thrown from methods or constructors.
Class Cast Exceptions are thrown when you try to cast a parent into it's child. (thrown in run time)
Note: Unchecked exceptions such as ArithmeticException , nullpointerException and RuntimeException needn't be declared in method signature.
The abstract methods in any abstract class must be defined once the subclass is not Abstract. Meaning that if an abstract class extends another abstract one you cannot have a body for the method in either class :)
- Any method written in an interface is set to be (public) by default.
- You can never use the word new before an interface or an abstract class name, but you can the name of the interface itself to have objects of that type. See below
- Interfaces can inherit from another interface
- Abstract class can implement an interface without providing an implementation for methods
- Interfaces can contain static methods with body
// Assume we have an interface/abstract class called Person,
and a class Student that extends person.
Person myPerson = new Person(); // This is wrong XXX.
Person myPerson = new Student(); // This is okay.
- An interface can't have instance variables (by logic because we can't make instances of it) but it may have static variables.
- A private constructor = you cannot instantiate an object from that class.
- You can't override public methods in the parent class with a private ones in the child class.
Overriding (children) has to be less restrictive !
OR the parent has to be more strict ;)
private -> default -> protected -> public.
from high to low restriction.
- You can't have a private class in a new .java file.
but you can have it inside the class you're working on. See below .
This is okay.
public class Person { // you can remove the public to use that class within the package only
private class Salah{
}
}
But this is wrong XXX:
private class Person {
//Constructors and methods
}
Note that you can use the default access modifier with the class in our case 1.
- public: Members available everywhere
- private: Members available only in the class
- default: Members available in the same class,package only.
- protected: Members available in the same class,package and another package but a subclass of this class. Note : default is more protected than the protected access modifier :O
Overriding is to override the logic of a function in the parent class. The overriding function must have the exact same signature (return type, parameters and name). However, overloading is the idea of adding methods with the same name but different signature. The old function can still be called normally.
Note: you cannot write the same method signature (same name, and same parameters in same locations) twice with a different return type.
class A {
protected void method()
{
System.out.println("AHello");
}
public static class B extends A {
public void method()
{
System.out.println("BHello");
}
public static void main(String args[])
{
A b = new B();
b.method();
}
}
Output: BHello
class A {
private void method()
{
System.out.println("AHello");
}
public static class B extends A {
public void method()
{
System.out.println("BHello");
}
public static void main(String args[])
{
A b = new B();
b.method();
}
}
Output: AHello
Note: At runtime it prints the output of the method from the subclass if the access modifier of the super class was public,protected or default , if it was private it prints the output of the method from the super class
An overriding method can throw any unchecked exceptions, regardless of whether the overridden method throws exceptions or not. However, the overriding method should not throw checked exceptions that are new or broader than the ones declared by the overridden method. The overriding method can throw narrower (Subclass of the thrown exceptions) or fewer exceptions than the overridden method.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
abstract class Super {
public String readFile(String path) throws IOException {
throw new IOException();
}
static class ExceptionsExample extends Super {
@Override
public String readFile(String path) throws FileNotFoundException {
Scanner sc = new Scanner(new File("E://test//sample.txt"));
String input;
StringBuffer sb = new StringBuffer();
while (sc.hasNextLine()) {
input = sc.nextLine();
sb.append(" "+input);
}
return sb.toString();
}
}
public static void main(String args[]) {
String path = "E://test//sample.txt";
ExceptionsExample obj = new ExceptionsExample();
try {
System.out.println(obj.readFile(path));
}catch(FileNotFoundException e) {
System.out.println("Make sure the specified file exists");
}
}
}
OUTPUT: Make sure the specified file exists
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
abstract class Super {
public String readFile(String path) throws IOException {
throw new IOException();
}
static class ExceptionsExample extends Super {
@Override
public String readFile(String path) throws Exception { //broader
Scanner sc = new Scanner(new File("E://test//sample.txt"));
String input;
StringBuffer sb = new StringBuffer();
while (sc.hasNextLine()) {
input = sc.nextLine();
sb.append(" "+input);
}
return sb.toString();
}
}
public static void main(String args[]) {
String path = "E://test//sample.txt";
ExceptionsExample obj = new ExceptionsExample();
try {
System.out.println(obj.readFile(path));
}catch(FileNotFoundException e) {
System.out.println("Make sure the specified file exists");
}
}
}
Compile error