Parâmetros de Tipos Delimitados
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 56 de 87.
Até agora, nossos parâmetros de tipo genérico podem aceitar qualquer tipo. Mas e se você precisar restringi-los?
Por exemplo, um método que calcula a soma de números não deve aceitar strings. Parâmetros de tipo limitados permitem limitar quais tipos podem ser usados com seus genéricos.
Use a palavra-chave extends para definir um limite superior em um parâmetro de tipo:
class NumberBox<T extends Number> {
private T value;
public NumberBox(T value) {
this.value = value;
}
public double getDoubleValue() {
return value.doubleValue(); // Pode chamar métodos de Number!
}
}
NumberBox<Integer> intBox = new NumberBox<>(42);
NumberBox<Double> doubleBox = new NumberBox<>(3.14);
// NumberBox<String> strBox = new NumberBox<>("Hi"); // Erro de compilação!O limite T extends Number significa que T deve ser Number ou qualquer uma de suas subclasses (Integer, Double, etc.). Isso também permite chamar methods definidos em Number no parâmetro de tipo.
Você pode especificar múltiplos limites usando &. Se um limite for uma classe, ele deverá vir primeiro:
class DataProcessor<T extends Number & Comparable<T>> {
public boolean isGreater(T a, T b) {
return a.compareTo(b) > 0;
}
}Aqui, T deve estender Number E implementar Comparable. Parâmetros de tipo limitados também funcionam com métodos genéricos:
public static <T extends Comparable<T>> T findMax(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
String result = findMax("apple", "banana"); // Retorna "banana"Parâmetros de tipo limitados tornam seus genéricos mais poderosos, garantindo a segurança de tipos e permitindo o acesso a métodos específicos do tipo limitado.
Desafio
FácilVamos criar uma calculadora de estatísticas que funcione apenas com tipos numéricos! Você usará parâmetros de tipo delimitados para garantir que sua calculadora processe apenas números, além de ter acesso a métodos úteis da classe Number.
Você organizará seu código em três arquivos:
NumberStats.java: crie uma classe genérica que calcule estatísticas para valores numéricos. Sua classeNumberStats<T extends Number>deve armazenar dois campos privados do tipoT:value1evalue2. Inclua um construtor que aceite ambos os valores. Adicione um métodogetSum()que retorne a soma dos dois valores como umdouble(use o métododoubleValue()herdado de Number). Adicione também um métodogetAverage()que retorne a média dos dois valores como umdouble.ComparableBox.java: crie uma classe genérica com múltiplos limites que possa encontrar o maior entre dois valores. Sua classeComparableBox<T extends Number & Comparable<T>>deve armazenar dois campos privados do tipoT:firstesecond. Inclua um construtor que aceite ambos os valores. Adicione um métodogetMax()que retorne o maior valor usandocompareTo(). Adicione também um métodogetMaxAsDouble()que retorne o maior valor convertido para umdouble.Main.java: coloque seus genéricos delimitados em ação! Você receberá quatro entradas: dois inteiros e dois valores de ponto flutuante.Primeiro, crie um
NumberStats<Integer>com os dois valores inteiros. Imprima a soma e a média:Integer sum: [sum] Integer average: [average]Em seguida, crie um
NumberStats<Double>com os dois valores de ponto flutuante. Imprima a soma e a média:Double sum: [sum] Double average: [average]Por fim, crie um
ComparableBox<Integer>com os dois valores inteiros e imprima:Max integer: [max] Max as double: [maxAsDouble]
Você receberá quatro entradas nesta ordem: primeiro inteiro, segundo inteiro, primeiro valor de ponto flutuante, segundo valor de ponto flutuante.
Observe como o limite T extends Number permite chamar doubleValue() em seu tipo genérico. Isso não seria possível com um parâmetro de tipo sem limite. E os múltiplos limites em ComparableBox garantem que você possa converter para double E comparar valores!
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler entradas
int int1 = scanner.nextInt();
int int2 = scanner.nextInt();
double double1 = scanner.nextDouble();
double double2 = scanner.nextDouble();
// TODO: Crie um NumberStats<Integer> com os dois valores inteiros
// Imprima a soma e a média no formato:
// Integer sum: [sum]
// Integer average: [average]
// TODO: Crie um NumberStats<Double> com os dois valores double
// Imprima a soma e a média no formato:
// Double sum: [sum]
// Double average: [average]
// TODO: Crie um ComparableBox<Integer> com os dois valores inteiros
// Imprima o máximo e o máximo como double no formato:
// Max integer: [max]
// Max as double: [maxAsDouble]
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão IteratorPratique por conta própria: Compilador de Java online