Presentation is loading. Please wait.

Presentation is loading. Please wait.

Type Safety, Generics, Lambdas, Class Object

Similar presentations


Presentation on theme: "Type Safety, Generics, Lambdas, Class Object"— Presentation transcript:

1 Type Safety, Generics, Lambdas, Class Object
Lecture 6 Java Type Safety, Generics, Lambdas, Class Object

2 Type Safety in Java Java is a statically typed language. Type safety:
Every variable must have a type at compile time Type safety: Making sure the object referenced by a variable is of a type compatible with the type of the variable Object type can be one of three options: The type of the object is equal to the type of its variable Person person = new Person(); The type of the object extends the type of its variable Person person = new Man(); //where Person is a Class The type of the object implements the type of its variable Person person = new Man(); //where Person is an Interface In Java, the compiler verifies type safety for us, and throws errors during compilation as needed

3 Generic Classes – Java 5+
Sometimes the language constructs weaken the type information, to enable more generic code: generic methods (Java8) generic classes (Java5) generic interfaces (Java5) Generics in Java are similar to templates in C++ Generics in Java can be defined on methods, classes and interfaces Code Example: X, Y – the generic types public class Pair<X, Y> { private X x, private Y y; public Pair(X x, Y y){ this.x = x; this.y = y; } public X getX(){ return x;} }

4 Generics and Primitives
Generics in Java do not allow the use of primitives! ArrayList<int> intArrayList; //compilation error! ArrayList<Integer> integerArrayList; //works fine! Solution: autoboxing and unboxing A convenient way to auto transform primitive data type to it’s corresponding java wrapper classes and vice versa Helpful in reducing code size – no need to convert primitive type to object type explicitly!

5 Java Wrapper Classes Each primitive type in Java has a corresponding wrapper class type Wrapper classes are objects that wrap the primitive type Wrapper Classes vs Primitive Types: Primitive types cannot be null while wrapper classes can be null Wrapper classes can be used in generics, primitive types cannot

6 Autoboxing and Unboxing
Autoboxing is done on primitive value in these cases: Passed as a parameter to a method that expects an object of the corresponding wrapper class Example: a method with Integer argument can be called by passing int, Java compiler will do the conversion of int to Integer. Assigned to a variable of the corresponding wrapper class Example, assigning a Long object to long variable Unboxing is done on wrapper classes in these cases: Passed as a parameter to a method that expects a value of the corresponding primitive type Example: a method with int argument can be called by passing Integer, Java compiler will do the conversion of Integer to int. Assigned to a variable of the corresponding primitive type Example, assigning a long primitive to a Long object

7 Autoboxing and Unboxing - Examples
In this autoboxing example, the added values are of primitive type int, while the list contains objects of type Integer: In this unboxing example, the values retrieved from the container are of an Integer object, while the summed up result of a primitive type of int: 1 2 3 List<Integer> li = new ArrayList<>(); for (int i = 1; i < 50; i += 2) li.add(i); public static int sumEven(List<Integer> li) { int sum = 0; for (Integer i: li) if (i % 2 == 0) sum += i; return sum; } How is this done? While compiling the compiler converts: Autoboxing example: line 3 to li.add(Integer.valueOf(i)); Unboxing example: line 5 to sum += i.intValue();

8 Generic Interfaces – Java 5
Generic interface are exactly the same as generic classes Syntax Example: public interface Person<T, E> { public Person(T age, E weight); public T getAge(); public E getWeight(); }

9 Generic Methods – Java 8+
public class Person { private int age; private int weight; public Person(int age, int weight) { this.age = age; this.weight = weight; } public int getAge() { return age; public int getWeight() { return weight; Given an array of Person objects what is the maximal object? Is it the heaviest Person? Maybe the oldest Person? It depends on how you want to compare the Person!

10 Generic Methods Implementation
public static <T> T max(T[] array, Comparator<T> comparator) { if (array.length == 0) throw new IllegalArgumentException("empty array"); int maxIndex=0; for (int i=1; i<array.length; i++) if (comparator.compare(array[maxIndex], array[i]) < 0) maxIndex = i; return array[maxIndex]; } Note the <T> in front of the method signature which parametrize the method.

11 Using Generic Methods public static class PersonComparatorByAge implements Comparator<Person> { public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } public static class PersonComparatorByWeight implements Comparator<Person> { return o1.getWeight() - o2.getWeight(); public static void main(String[] args) { Person[] Persons = {new Person(7,50), new Person(9,200), new Person(3,100)}; System.out.println(max(ints, new PersonComparatorByWeight ()).getWeight()); // 200 System.out.println(max(Persons, new PersonComparatorByAge()).getAge()); // 9

12 Generics Limitations Cannot use primitive types, only objects
Generics are erased at runtime: During compilation the compiler knows that List<Integer> is not a List<String>. At run time, both of them looks like List<Object> This limitation can be seen in the following code: This won’t compile as the compiler knows that at runtime the defined methods has the same signature!

13 Generics Limitations More on “type erasure”:
You can do: List<String> list; ((List)list).add(new Object()); An error will be thrown only when you get the value of a String. Arrays of generic types cannot be instantiated directly i.e., the following will not compile: But can be worked around this way:  pairs is an array of Pair without any additional generic type information.

14 Default Methods – Java 8+
Default methods enable us to add new functionalities to interfaces without breaking the classes that implement that interface.  Allows us to implement methods directly in the interface! We add default keyword before the access modifier of the method we wish to implement. This implementation will be the default implementation for all classes implementing this interface, and did not override it. Default methods tutorial:

15 Default Method - Example
interface Stack<E> { void push(E something); E pop(); int size(); boolean isEmpty(); } interface Stack<E> { void push(E something); E pop(); int size(); default boolean isEmpty(){ return (size())==0); } Implementation of isEmpty()wil act as the default implementation for all implementing classes, as long as the class does not overwrite the implementation. If the same default method is implemented in two different interfaces, and our class extends both interfaces, we must overwrite the default method.

16 Wildcards in Java Pair<Object,Object> is not a super-class of Pair<Integer,Integer>. Pair<?,?> is a super-class of Pair<Integer,Integer>. Bad example: This method accepts only Collection<Object>

17 Wildcards in Java (more at: https://docs. oracle
Good example: This method accepts any Collection However The compiler does not allow to add() because the inner type is unknown at compile time.

18 Anonymous Classes Anonymous classes enable you to make the code more concise - מתומצת They allow declaring and instantiating a class at the same time They are like local classes except that they do not have a name They are useful when the code of a local class needs to be executed once only during the execution of the program

19 Anonymous Class Example
public static void main(String[] args) { Person[] Persons = {new Person(7,50), new Person(9,200), new Person(3,100)}; System.out.println(max(Persons, new Comparator<Person>(){ public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } }).getAge()); // prints 9 return o1.getWeight() - o2.getWeight(); }).getWeight()); // prints 200 } In the previous example we implemented two classes: PersonComparatorByWeight PersonComparatorByAge And we have used them once! A good place to use anonymous classes here

20 Lambdas – Java 8+ Using anonymous classes to implement interfaces of one method results in a long (relatively) and unreadable syntax We can use lambdas instead of anonymous classes which provide easy to implement as well as to readable syntax Full material:

21 Lambda Advantages Allows writing a method in the same place to be used
Especially useful in places where a method is being used only once, and the method definition is short. Saves the effort of declaring and writing a separate method to the containing class (arg1, arg2, ..., argN) -> { body } (type1 arg1, type2 arg2, ..., typeN argN) -> { body }

22 Examples (int a, int b) -> { return a + b; }
() -> System.out.println("Hello World"); (String s) -> { System.out.println(s); } () -> 42 () -> { return }; Guide:

23 Persons Example – Using Lambda
public static void main(String[] args) { Person[] Persons = {new Person(7,50), new Person(9,200), new Person(3,100)}; System.out.println(max(Persons, (Person o1, Person o2) -> { return o1.getAge() - o2.getAge(); }).getAge()); System.out.println(max(Persons, (Person o1, Person o2) -> { return o1.getWeight() - o2.getWeight(); }).getWeight()); } Anonymous Classes: public static void main(String[] args) { Person[] Persons = {new Person(7,50), new Person(9,200), new Person(3,100)}; System.out.println(max(Persons, new Comparator<Person>(){ public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } }).getAge()); // prints 9 return o1.getWeight() - o2.getWeight(); }).getWeight()); // prints 200 }

24 The Class Object The Class object is static: getClass(): getName():
There is a special class called Class Instances of Class represent classes and interfaces in a running Java application Class has no public constructor Class objects are constructed automatically by the JVM, one object per implemented class The Class object is static: For a class Person, Person.class returns an object of the type Class getClass(): For an object a of type Person, person.getClass() returns an object of the type Class. getName(): Returns corresponding class name isAssignableFrom(Class) The calling Class represents a superclass or super-interface of the class represented by the given Class object

25 isAssignableFrom(Class) Example
class A {} class B extends A {} class C extends B {} public class Example {     public static void main(String[] args) {         A a = new A();         B b = new B();         C c = new C();         System.out.println(                 A.class.isAssignableFrom(B.class)); //true                 a.getClass().isAssignableFrom(C.class)); //true                 B.class.isAssignableFrom(c.getClass())); //true                 b.getClass().isAssignableFrom(a.getClass())); //false                 C.class.isAssignableFrom(B.class)); //false     } } class A {} class B extends A {} class C extends B {} public class Example { public static void main(String[] args) { A a = new A(); B b = new B(); C c = new C(); System.out.println( A.class.isAssignableFrom(B.class)); //true System.out.println( a.getClass().isAssignableFrom(C.class)); //true System.out.println( B.class.isAssignableFrom(c.getClass())); //true System.out.println( b.getClass().isAssignableFrom(a.getClass())); //false System.out.println( C.class.isAssignableFrom(B.class)); //false } }

26 Printing a Class Structure
class A { private int intValue; private String stringValue;} class B extends A { private double doubleValue;} class Example {    public static void print(Class c) {     System.out.println("class: " + c.getName());     System.out.println("fields: ");     for (Field f : c.getDeclaredFields())        System.out.println("\t" + f.getName() + ": " + f.getType());    System.out.println("methods: ");   for (Method m : c.getDeclaredMethods())       System.out.println("\t" + m.getName() + ": " + m.toString());    System.out.print("inherits from ");    print(c.getSuperclass());  }   public static void main(String[] args) { print(B.class); } } import java.lang.reflect.Field; import java.lang.reflect.Method; class A { private int aInt; private String aString; } class B extends A { private double bDouble; } class Example { public static void print(Class c) { System.out.println("class: " + c.getName()); if (c.getDeclaredFields().length > 0) { System.out.println("fields: "); for (Field f : c.getDeclaredFields()) { System.out.println("\t" + f.getName() + ": " + f.getType()); } } if (c.getDeclaredMethods().length > 0) { System.out.println("methods: "); for (Method m : c.getDeclaredMethods()) { System.out.println("\t" + m.getName() + ": " + m.toString()); } } if (c.getSuperclass() != null) { System.out.print("inherits from "); print(c.getSuperclass()); } } public static void main(String[] args) { print(B.class); } }

27


Download ppt "Type Safety, Generics, Lambdas, Class Object"

Similar presentations


Ads by Google