Dei uma olhada (passei o código abaixo para o compilador), e realmente as alternativas corretas são A, C, D e G.
import java.util.*;
class A {}
class B extends A {}
class C extends A {}
class D extends B {}
class Assignable {
public static void main(String[] args) {
List list = new ArrayList();
List<A> listA = new ArrayList<A>();
List<B> listB = new ArrayList<B>();
List<Object> listObject = new ArrayList<Object>();
List<D> listD = new ArrayList<D>();
List<?> listWhat = new ArrayList<Object>();
List<? extends A> listExtendsA = new ArrayList <B>();
List<? extends B> listExtendsB = new ArrayList <D>();
//A. The type List<A> is assignable to List. => OK
list = listA;
//B. The type List<B> is assignable to List<A>. => Incompatible types
listA = listB;
//C. The type List<Object> is assignable to List<?>. => OK
listWhat = listObject;
//D. The type List<D> is assignable to List<? extends B>. => OK
listExtendsB = listD;
//E. The type List<? extends A> is assignable to List<A>.
listA = listExtendsA; // => incompatible types
//F. The type List<Object> is assignable to any List reference.
list = listObject; // => OK
listA = listObject; // => incompatible types
//G. The type List<? extends B> is assignable to List<? extends A>. => OK
listExtendsA = listExtendsB;
}
}
Só mais uma sujestão :
esse tipo de criação de um objecto tem um propósito importante para passagens por referências,ou seja caso vc tenha:
[code]
class Animal{
}
class Dog extends Animal{
}
class Text{
public static void main(String…a){
List<? extends Animal> lista_animal=new ArrayList();
List lista_dog=new ArrayList();
//agora vc pode tranquillamente fazer
lista_animal=lista_dog;//vc esta referenciando uma Objecto listaDog
//agora o contrario
List<? super Dog> lista_dog2=new ArrayList();
List lista_animal2=new ArrayList();
lista_dog2=lista_animal2;//agora vc consegue referenciar algo que esta acima na arvore de heranca!!que normalmente não é permitido em java
Isso não é válido. Na hora de criar o elemento o tipo tem que ser conhecido. Só na hora de referenciar é que ele não precisa ser conhecido. Ou seja:
// Válido. É criado um ArrayList cujos elementos são do tipo A.
List<? extends A> lista = new ArrayList<A>();
// Inválido é criado um ArrayList cujos elementos são de um tipo desconhecido.
// O compilador reclama: Você tem que saber que tipo você vai criar.
List<? extends A> lista = new ArrayList<? extends A>();
Bom pelo que a gente viu no metodo getObject B é uma classe concreta ja que usa operador new nela, e tipo
classes concretas não podem ter metodos abstracts…além do mais se ela fosse uma classe abstrata tbem…
metodos aabstract não terminam com chaves e sim com parenteses…
lembre-se que vc está especificando apenas sua assinatura…não seu corpo…por iss ele é abstrato.
Este “? extends A”, quer dizer “A ou qualquer uma de suas subclasses”.[/quote]
Imagine essa estrutura:
abstract class A {
public abstract void facaAlgo();
}
B extends A {
public abstract void facaAlgo() { }
}
class Teste {
public static void main(String... args) {
List<? extends A> lista = new ArrayList<? extends A>();
// nesse momento eu faço uma chamada ao metodo getObjeto que me
// retorna um objeto tipo A. até aqui sem problemas.
// mas A é uma classe abstrata que contem métodos abstratos.
// como posso garantir que o objeto que esta vindo é uma subclasse
// de A e que implemente seus métodos abstratos?
// se eu tentar criar uma instancia de A, não vai funcionar
lista.add(getObjeto());
}
A getObjeto() {
return new B();
}
}