• Skip to primary navigation
  • Skip to main content
  • Skip to footer

Codemotion Magazine

We code the future. Together

  • Discover
    • Events
    • Community
    • Partners
    • Become a partner
    • Hackathons
  • Magazine
    • Backend
    • Dev community
    • Carriere tech
    • Intelligenza artificiale
    • Interviste
    • Frontend
    • DevOps/Cloud
    • Linguaggi di programmazione
    • Soft Skill
  • Talent
    • Discover Talent
    • Jobs
    • Manifesto
  • Companies
  • For Business
    • EN
    • IT
    • ES
  • Sign in
ads

Fabrizio TedeschiSettembre 26, 2024 2 min di lettura

Un limite dei tipi generici in Java

Linguaggi di programmazione
java message modeling
facebooktwitterlinkedinreddit

Problema

Si considerino la seguente classe Person e le classi figlie Manager e Employee definite come segue:

public static class Person {
    String name;
    public Person(String name) { this.name = name; }
}

public static class Manager extends Person{
    public Manager(String name) { super(name); }
}

public static class Employee extends Person{
   public Employee(String name) { super(name); }
}Code language: JavaScript (javascript)

Si consideri ora un generico metodo statico che accetta due parametri di un tipo generico T e ritorna un oggetto di tipo T . Al tipo T viene inserito il vincolo <T extends Person> ossia il tipo T dovrà possedere ALMENO ciascuno degli attributi e dei metodi di person.

Recommended article
Maggio 7, 2025

Evitare la duplicazione del codice sfruttando le high-order function in JavaScript

Fabrizio Tedeschi

Fabrizio Tedeschi

Linguaggi di programmazione
public static T foo(T t1, T t2){
    //Do something
    return …
}Code language: PHP (php)

Si supponga di definire le seguenti istanze p1 e p2 e di effettuare la seguente invocazione del metodo foo() :

Employee p1 = new Employee("John");
Manager p2 = new Manager("Johanna");

Person out = foo(p1, p2);Code language: JavaScript (javascript)
Si vuole ora imporre che entrambi i parametri passati al metodo foo() siano dello stesso tipo facendo in modo che il compilatore segnali un errore in caso contrario.

Osservazione

Eseguendo l’invocazione del metodo sopra riportata NON viene generato alcun errore di compilazione in quanto sia p1 (di tipo Employee) che p2 (di tipo Manager) rispettano i vincoli imposti dal tipo generico T (infatti essi possiedo entrambi gli attributi di Person).

Per comprendere al meglio il problema è necessario analizzare i meccanismi di compilazione e precompilazione del codice.

Il ruolo del type erasure

Il type erasure è il meccanismo di precompilazione che provvede a rimpiazzare tutti i tipi generici con il tipo di oggetto con maggior compatibilità (rispettando eventuali limitazioni poste).

Nel caso in esame, poiché viene fissato il vincolo <T extends Person>, il tipo generico T sarà rimpiazzato con il tipo di oggetto in grado di garantire la miglior compatibilità e di rispettare le limitazioni imposte. Si otterrà perciò:

public static Person foo(Person t1, Person t2){
    //Do something
    return …
}Code language: PHP (php)

Risulta quindi chiaro come, effettuando l’invocazione proposta sopra, sia p1 che p2 siano accettati dal compilatore, in quanto entrambi “discendenti” di Person.

Type inference

In caso vengano passati come parametri di foo() istanze di oggetti dello stesso tipo entra in gioco il ruolo del meccanismo di type inference che provvede ad utilizzare come tipo di compilazione la sotto-classe delle istanze passate come argomenti.

Nel caso in oggetto essendo entrambe le classi, Employee e Manager, figlie dirette di Person, la classe più adatta da utilizzare al momento della compilazione sarà Person.

In caso venissero passate al metodo due istanze di Manager, la classe più adatta da utilizzare al momento della compilazione sarà Manager.

Possibili soluzioni al problema

Alla luce di quanto osservato finora sembra di aver rilevato un limite imposto dai tipi generici: nel caso vengano passati ad un metodo due istanze di tipo generico T limitato tramite la sintassi <T extends C>, se le istanze passate come parametri del metodo sono entrambe sotto-classi di C non è possibile produrre errori in compile-time in caso le istanze passate come parametri siano di tipi differenti.

Sono illustrati di seguito possibili soluzioni alternative al problema.

Soluzione alternativa 1 – Classe ausiliaria

Nel caso si conosca il numero di parametri dello stesso tipo da passare al metodo, definire un classe con tipo generico che accetti i vari oggetti e venga successivamente passata come unico parametro del metodo foo().

//New class with two same-type objects
public static class Pair<P>{
    private P first;
    private P second;
    public Pair(P first, P second) {
        this.first = first;
        this.second = second;
    }

    public P getFirst() {
        return first;
    }

    public P getSecond() {
        return second;
    }
}

//New foo definition
public static <T extends Person> T foo(Pair<T> pair){
    //Do something
    return ...
}

Employee p1 = new Employee("John");
Employee p2 = new Employee("Francis");
Manager p3 = new Manager("Johanna");

//Accepted
Pair<Employee> pair = new Pair<>(p1, p2);
Person out = foo(pair);

//Compile error (p1 e p3 are different types)
Pair<Employee> pair2 = new Pair<>(p1, p3);
Person out = foo(pair2);Code language: PHP (php)

Soluzione alternativa 2 – Verifica in run-time

Tramite l’utilizzo del metodo getClass() è possibile verificare a run-time se i parametri passati sono istanze di oggetti dello stesso tipo:

public static <T extends Person> T my_method(T t1, T t2){
    if(t1.getClass() != t2.getClass()){
        throw new IllegalArgumentException("Different type arguments");
    }

    //Do something
    return ...
}Code language: PHP (php)
Codemotion Collection Background
Dalla community
Selezionati per te

Vuoi scoprire più articoli come questo? Dai un’occhiata alla collection Dalla community dove troverai sempre nuovi contenuti selezionati dal nostro team.

Share on:facebooktwitterlinkedinreddit

Tagged as:tipi generici

Fabrizio Tedeschi
Studente di Ingegneria Informatica e docente di informatica presso istituiti di istruzione secondaria di 2^ grado. Credo che la divulgazione e l'informazione abbiano un ruolo fondamentale nel comprendere al meglio gli sviluppi ed i progressi della tecnologia e dell'informatica.
Founder Mode vs Manager Mode: quale è il tuo stile?
Previous Post
Collaborare è il nostro superpotere – le community open source
Next Post

Footer

Discover

  • Events
  • Community
  • Partners
  • Become a partner
  • Hackathons

Magazine

  • Tech articles

Talent

  • Discover talent
  • Jobs

Companies

  • Discover companies

For Business

  • Codemotion for companies

About

  • About us
  • Become a contributor
  • Work with us
  • Contact us

Follow Us

© Copyright Codemotion srl Via Marsala, 29/H, 00185 Roma P.IVA 12392791005 | Privacy policy | Terms and conditions