Java Generics Summary

Introduction

I've been researching generics again for the past few days, so after giving a brief overview of generics, I decided to summarize the following two contents as a memo.

--Generics scope --Talk about type variables

Generics overview

Anyway, I would like to reorganize the merits of using Generics. It ** will notify you at compile time if you try to insert an object of the wrong type ** (quoted from Effective Java 3rd Edition Chapter 5 Generics). As a result, similar processing can be realized for various types within the range in which type safety can be guaranteed. Now, I would like to show a concrete example in code. Here, I would like to recognize the goodness of writing in generics by comparing arrays and generics. Write the definition of the list, add to the list, and retrieve it without using generics as follows.

ArrayList list = new ArrayList(); 
list.add("hoge"); 
String s = (String) list.get(0);

Since it is extracted as Object type, it is necessary to explicitly cast it, and if there is an error (such as assigning with int and extracting with String), you will not notice the error unless you move it. ← This is very painful. Write the definition of the list using generics, the addition to the list, and the retrieval as follows.

ArrayList<String> list = new ArrayList<String>(); 
list.add("hoge"); 
String s = list.get(0);

I get an error when compiling. (You can notice the mistake before executing it ← This is very nice)

About the scope of Generics

Generics has two scopes. Method scope and instance scope. An overview is given for each.

Method scope

First, the syntax is shown below.

SetInt.java


public class SetInt{
  public <E> Set<E> union(Set<E> s1,Set<E> s2){
    // (Example)Processing to add s1 and s2
 }
}

The first thing you will notice is the after the access modifier public. This is a type variable declaration. This declaration allows us to define an association that the argument and return value are of the same type within the scope of the method. Method-scoped generics declarations can be used not only in instance methods, but also in static methods and constructors. When calling, there are cases where it is called as it is and cases where it is called by explicitly specifying the type.

When calling as it is
Set<Integer> result = SetInt.union(Set<Integer>,Set<Integer>);
When calling by explicitly specifying the type
Set<Integer> result = SetInt.<Integer>union(Set<Integer>,Set<Integer>);

In addition, exception handling can be called as follows by explicitly specifying the type.

Hoge.java


public class Hoge{
	public <E extends Exception> void example() throws E {};
	public  void test() {
		try {
			this.<IOException>example();
		} catch (IOException e) {
			//Exception handling at IOException exception catch
		}
		try {
			this.<SQLException>example();
		} catch (SQLException e) {
			//Exception handling at SQLException exception catch
		}
	}	
}

Instance scope

It's more often seen than method scope, and I feel that it's usually dealt with in introductory books. An example is shown below.

Stack.java


public class Stack<E> {
  private E elements;
  public void push(E e) {
	//Process to push to elements
  }
  public E pop() {
	//Processing to extract E from elements
  }
}

You can define associations where the arguments, return values, and instance field types of multiple declared instance methods (two above) are the same.

Story around type variables

Knowledge of "covariance, contravariance, immutability" and "Liskov substitution principle" is a prerequisite. This article is easy to understand about the former (https://www.thekingsmuseum.info/entry/2016/02/07/235454) In the following memo, as an example, there are classes A, B, and C, respectively, and they are verified as having an inheritance relationship of C extends B and B extends A, respectively.

Covariant

It can be defined as follows.

List<? extends B> extendsBList = new ArrayList<C>();

The above extendsAList has the following properties.

  1. B-type and C-type variables can be extracted from extendsBList.
  2. Only null type can be stored in extendsBList.

Aside from property 1, property 2 remains questionable. The process by which property 2 is derived is summarized below.

Why can't I store anything other than null type in extendsBList?

For example, it can be stored in extendsBList and extendsBList.add (new B ()); holds. However, please refer to the initialization code of extendsBList once again. It is initialized with ArrayList type. If B could be added (), the B type would be added () to the ArrayList type, causing a contradiction. Therefore, in List <? Extends B>, add () can be added to List and List that can be assigned to List <? Extends B> so that the safety of the type is not broken. It is constrained so that only new things can be added (). Since it has only a null type, property 2 holds.

Rebellion

It can be defined as follows.

List<? super B> superBList = new ArrayList<A>();

The above superBList has the following properties.

  1. superBList can store B type and A type variables.
  2. The type extracted from superBList is Object type.

Question remains in property 2. However, the fact that property 1 holds means that the object retrieved by get () may be an object type higher than the B type. From this, when <? Super B> is set, the object obtained by get () can be received only by the Object type located at the top of all types. Instead of accepting the storage, it becomes impossible to specify the type to return.

About PECS principles

Effective Java 2nd Edition Item 28 describes the PECS principles. Quoted below.

In the function, if the role of the generics type argument is "Producer", use extends, and if it is "Consumer", use super. A producer is an argument that creates (provides) some value in a function. On the other hand, a consumer is an argument that consumes (uses) some value in a function. This principle is also known as "PECS" for Producer-Extends and Consumer-Super.

Based on the discussion of covariance and contravariance, we can understand why we do so. Take the Hoge class as an example.

  • To generate (provide) a value from the function side, to get the value from the function user side, that is, to retrieve the value, use <? Extends Hoge>.
  • From the function side, consuming (using) the value means setting the value from the function user side, that is, <? Super Hoge> when storing the value.

In a method, using extends as the argument of the method and super as the return value of the method can take a wider implementation of the method.

at the end

I would like to review the content of the article from time to time. Also, when I can write generics, I want to be able to design using generics.

reference

(https://www.amazon.co.jp/exec/obidos/ASIN/B078H61SCH/xray2000-22/)

Recommended Posts

Java Generics Summary
[Java] Generics
Java knowledge summary
[Java] Generics sample
Java Generics (Notes)
Java related summary
Java 8 documentation summary
Java 11 document summary
Java 12 new feature summary
[Summary] Java environment preparation
effective java 3rd summary
Java 13 new feature summary
Frequently used Java generics
Java static [Personal summary]
Thread safe summary ~ Java ~
Java Primitive Specialization Summary
Java development link summary
Personal summary about Java
Java 10 new feature summary
java regular expression summary
Java 14 new feature summary
Summary of Java support 2018
Java design pattern summary
Java reserved word summary
Java8 Stream Rough Summary
What is Java Assertion? Summary.
[Java11] Stream Summary -Advantages of Stream-
Progate Java (Beginner) Review & Summary
[Java] Generics classes and generics methods
[Java] Summary of regular expressions
[Java] Summary of operators (operator)
Java8 stream, lambda expression summary
Object-oriented summary by beginners (Java)
Summary
Java
Summary of Java language basics
Java tips --Spring execution Summary
[Java] Summary of for statements
Summary of Java Math class
java Generics T and? Difference
Java
[Java11] Stream Usage Summary -Basics-
[Java] Summary of control syntax
Summary of java error processing
[Java] Summary of design patterns
[Java] Summary of mathematical operations
Consideration on Java Persistence Framework 2017 (Summary) -1
[For beginners] Summary of java constructor
Java release date and EOL summary
Summary of [Java silver study] package
Effective Java 3rd Edition Chapter 5 Generics
AtCoder 400 points algorithm summary (Java edition)
[Java] Try to implement using generics
Java generics (defines classes and methods)
Java "pass by reference" problem summary
Generics of Kotlin for Java developers
Java EE 8 (Jakarta EE 8) New feature summary
Summary of object-oriented programming using Java
Java learning (0)
Studying Java ―― 3
[Java] array