DEV Community

FUNDAMENTOS JAVA
FUNDAMENTOS JAVA

Posted on

Tipos limitados

  • Os parâmetros de tipo em genéricos podem ser substituídos por qualquer classe.

  • Em alguns casos, é útil limitar os tipos que podem ser usados como parâmetro de tipo.

  • Um exemplo: criar uma classe genérica para armazenar valores numéricos e executar funções matemáticas como calcular o recíproco ou o componente fracionário.

  • A classe genérica deve permitir operar com diferentes tipos de números, como Integer, Float e Double.

  • O tipo dos números é especificado genericamente por meio de um parâmetro de tipo.

// NumericFns tenta (sem sucesso) criar uma
// classe genérica que possa executar várias
// funções numéricas, como calcular o recíproco ou o
// componente fracionário, dado qualquer tipo de número.
class NumericFns<T> {
T num;
// Passa para o construtor uma referência
// a um objeto numérico.
NumericFns(T n) {
num = n;
}
// Retorna o recíproco.
double reciprocal() {
return 1 / num.doubleValue(); // Erro!
}
// Retorna o componente fracionário.
double fraction() {
return num.doubleValue() - num.intValue(); // Erro!
}
// ...
}

  • A classe NumericFns não compila porque o compilador não reconhece métodos como doubleValue() e intValue() para o tipo genérico T.

  • Isso ocorre porque o compilador não sabe que apenas tipos numéricos deveriam ser usados como argumento para T.

  • Para resolver, é necessário limitar o tipo genérico T a classes derivadas de uma superclasse específica.

  • Em Java, isso é feito com a cláusula extends, como em <T extends superclasse>.

  • No caso de NumericFns, o problema é resolvido definindo Number como limite superior para T.

// Nesta versão de NumericFns, o argumento de
// tipo de T deve ser Number ou uma classe
// derivada de Number.
class NumericFns<T extends Number> {
T num;
// Passa para o construtor uma referência
// a um objeto numérico.
NumericFns(T n) {
num = n;
}
// Retorna o recíproco.
double reciprocal() {
return 1 / num.doubleValue();
}
// Retorna o componente fracionário.
double fraction() {
return num.doubleValue() - num.intValue();
}
// ...
}
// Demonstra NumericFns.
class BoundsDemo {
public static void main(String args[]) {
// Integer pode ser usado porque é subclasse de Number.
NumericFns<Integer> iOb =
new NumericFns<Integer>(5);
System.out.println("Reciprocal of iOb is " +
iOb.reciprocal());
System.out.println("Fractional component of iOb is " +
iOb.fraction());
System.out.println();
// Double também pode ser usado.
NumericFns<Double> dOb =
new NumericFns<Double>(5.25);
System.out.println("Reciprocal of dOb is " +
dOb.reciprocal());
System.out.println("Fractional component of dOb is " +
dOb.fraction());
// Essa parte não será compilada porque String
// não é subclasse de Number.
// NumericFns<String> strOb = new NumericFns<String>("Error");
}
}

  • Limitando o tipo genérico T com Number, o compilador garante que métodos como doubleValue() estejam disponíveis para T.

  • Essa restrição também impede a criação de objetos NumericFns com tipos não numéricos, como String.

  • Tipos limitados são úteis para garantir a compatibilidade entre parâmetros de tipo, como demonstrado na classe Pair, que armazena dois objetos compatíveis.

//Aqui, V deve ser do mesmo tipo de T ou uma subclasse de T.
class Pair<T, V extends T> {
T first;
V second;
Pair(T a, V b) {
first = a;
second = b;
}
// ...
}

  • A classe Pair usa dois parâmetros de tipo, T e V, onde V estende T.

  • Isso garante que os dois argumentos passados ao construtor de Pair sejam do mesmo tipo ou de tipos relacionados.

  • Exemplo: T pode ser uma superclasse, enquanto V é a mesma classe ou uma subclasse de T.

// Isto está certo porque T e V são Integer.
Pair<Integer, Integer> x = new Pair<Integer, Integer>(1, 2);
// Isto está certo porque Integer é uma subclasse de Number.
Pair<Number, Integer> y = new Pair<Number, Integer>(10.4, 12);

  • Não é possível ter:

// Esta linha causa um erro, porque String não é
// subclasse de Number
Pair<Number, String> z = new Pair<Number, String>(10.4, "12");

  • String não é subclasse de Number, o que viola o limite especificado por Pair.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay