Se eu lhe dissesse diretamente o que são genéricos, realmente não posso.
Defina uma classe de ponto coordenado que possa salvar vários tipos de dados, como números inteiros, tipos de ponto flutuante e tipos de string.
Como o tipo de variável é inicialmente incerto, é fácil pensar em usar a classe pai de todos os tipos, ou seja, a classe Object.
Chega de bobagens, use código para refleti-lo
Exemplo 1: Use Object para implementar entrada de tipo de dados incerto
//Use Object para representar tipos incertos
ponto público (Objeto x, Objeto y) {
este.setX(x);
este.setY(y);
}
public void setX(Objeto x) {
isto.x = x;
}
objeto público getX() {
retornar x;
}
public void setY(Objeto y) {
isto.y = y;
}
objeto público getY() {
retornar y;
}
}
//classe de teste
demonstração de classe pública {
public static void main(String[] args) {
System.out.println("Use números de ponto flutuante para representar coordenadas: ");
Ponto p = novo Ponto(12.23,23.21);
//Aqui, a classe Object é convertida na classe Double e, em seguida, desempacotada automaticamente. Os dois seguintes são iguais.
System.out.println("Coordenadas X" + (Double)p.getX());
System.out.println("Coordenadas Y" + (Double)p.getY());
System.out.println();
System.out.println("Use números inteiros para representar coordenadas: ");
Ponto p2 = novo Ponto(12, 23);
System.out.println("Coordenadas de X" + (Inteiro)p2.getX());
System.out.println("Coordenadas Y" + (Inteiro)p2.getY());
System.out.println();
System.out.println("Representando coordenadas como uma string: ");
Ponto p3 = novo Ponto("29 graus de latitude norte", "113 graus de longitude leste");
System.out.println("Coordenadas X" + (String)p3.getX());
System.out.println("Coordenadas Y" + (String)p3.getY());
}
}
Você deve entender claramente que tipo está transmitindo e, em seguida, reduzi-lo antes de poder usá-lo.
Embora isto atenda à demanda, também implica um fator inseguro. Por que é considerado implícito?
Por exemplo, usamos new Point(12.23, "29 graus de latitude norte") para construir um objeto Point
Em seguida, use (Double) para transformá-lo para baixo. Qual será o resultado?
Sim, a compilação será aprovada, mas uma vez executada, ocorrerá uma exceção de conversão de tipo
Também é muito simples evitar exceções de conversão de classe. Basta substituir a declaração Object por uma declaração de tipo fixo (como: String x, String y), para que um erro seja relatado durante a compilação.
Então você pode encontrar os erros e fazer correções
Mas então não seremos capazes de atender à demanda.
Para evitar riscos de segurança e substituir vários tipos de dados, essas pessoas talentosas introduziram o conceito de genéricos no JDK1.5
Vamos ver como reescrever o código acima usando genéricos
Exemplo 2: classe genérica
demonstração de classe pública {
public static void main(String[] args) {
System.out.println("Use números de ponto flutuante para representar coordenadas: ");
//Após reescrever com genéricos, não há necessidade de realizar transformação descendente nos dados utilizados.
Ponto<Duplo> p = new Ponto<Duplo>(12.23,23.21);
System.out.println("Coordenadas X" + p.getX());
System.out.println("Coordenadas Y" + p.getY());
System.out.println();
System.out.println("Use números inteiros para representar coordenadas: ");
Ponto<Integer> p2 = new Point<Integer>(12, 23);
System.out.println("Coordenadas X" + p2.getX());
System.out.println("Coordenadas Y" + p2.getY());
System.out.println();
System.out.println("Representando coordenadas como uma string: ");
Point<String> p3 = new Point<String>("29 graus de latitude norte", "113 graus de longitude leste");
System.out.println("Coordenada X" + p3.getX());
System.out.println("Coordenadas Y" + p3.getY());
}
}
Se passarmos deliberadamente diferentes tipos de dados neste momento:
Point<Double> p = new Point<Double>("29 graus de latitude norte",12.22);
Então, um erro será relatado durante a compilação
Embora os genéricos sejam definidos, se você não usar o mecanismo genérico no construtor, ele tratará os dados como Objeto.
O objetivo disso é principalmente ser compatível com códigos antigos anteriores ao JDK1.4, como
Ponto p = novo Ponto(22.11,23.21);
O resultado final da execução é o mesmo, mas uma mensagem de aviso será exibida durante a compilação.
Exemplo 3: Métodos genéricos
Como você pode ver no exemplo acima, uma vez especificado o tipo de objeto no construtor, o mesmo tipo será usado em toda a classe
O exemplo mais típico é usado na estrutura de coleção, como: ArrayList<Integer> al = new ArrayList<Integer>();
Neste momento, todos os tipos de objetos operados em al são inteiros.
Porém, às vezes não queremos fixar o objeto de operação, mas queremos usar a tecnologia genérica de forma mais flexível.
Neste momento, você pode tentar o método genérico
public <E> void show(E e) {
System.out.println(e);
}
}
demonstração de classe pública {
public static void main(String[] args) {
Imprimir p = new Imprimir();
imprimir(12);
print("olá");
p.show(novo Inteiro(33));
p.mostrar(23);
}
}
Na verdade, desta forma, não há grande diferença em usar objetos Object em métodos.
Além do mais, após o JDK1.5, a função de unboxing automático foi adicionada, eliminando a necessidade de transformação descendente.
Exemplo 4: Interface genérica
//Método de implementação um:
classe InterDemo1 implementa Inter<String> {
impressão pública void(String t) {
System.out.println("imprimir: " + t);
}
}
//Método de implementação dois:
classe InterDemo2<T> implementa Inter<T> {
impressão pública vazia (T t) {
System.out.println("imprimir: " + t);
}
}
classe Demonstração {
public static void main(String[] args) {
InterDemo1 id1 = new InterDemo1();
id1.print("olá");
InterDemo2<Integer> id2 = new InterDemo2<Integer>();
id2.print(novo Inteiro(23));
}
}
Existem duas maneiras de implementar uma interface genérica. Uma é especificar o tipo genérico ao implementá-la.
A outra é ainda usar genéricos e determinar o tipo genérico durante a construção.