Pegadinha no exame

27 respostas
LPJava

ae galera, estudando as pegadinhas do exame, aproveitei e vou postar um codigo e a galera que está estudando diz se compila ou nao compila… e se nao compilar pq nao compila…

class Camilo{

	static  void nome(){}
	public static void main(String ar[]){

	}
}
class Neto extends Camilo{
	 void nome(){}
}

agora esse tb tinha la

class Camilo{

	 void nome(){}
	public static void main(String ar[]){

	}
}
class Neto extends Camilo{
	final void nome(){}
}

deixem a opniao de vocês depois colocar a minha para ver se estou no caminho certo :d
flw! rumo a scjp :smiley:

27 Respostas

diego2005

O primeiro código não compila, pois não podemos sobscrever métodos estáticos. O segundo compila sdem problemas…

T+

Marcio_Nogueira

ambos não compilam.

CarlosEduardoDantas

diego2005:
O primeiro código não compila, pois não podemos sobscrever métodos estáticos. O segundo compila sdem problemas…

T+

certinho :wink:

pegadinha boa…

só pra frisar o assunto… no segundo exemplo, se fosse o inverso, ou seja, se o metodo nome() da classe Camilo fosse marcado com o modificador final, não compilaria… mas se fosse marcado como private, compilaria sem problemas, apenas não poderia ser subscrito. :wink:

W

HA! pegadinha do malandro! meu xuxu!

CarlosEduardoDantas

certeza? :roll:

LPJava

pera ai galera houve um pouco de confusao, vamos la a questao… apesar de ser xuxu como falaram… mais tem muita dessa questao… no exame… infelizmente o “xuxu” deve ser estudado…
Marcio_Nogueira - a segunda compila q tem o final… a com o static q n compila.

a questao é que os metodos static nao sao subscrito e sim redefindos… e por isso que o primeiro nao compila. pq é o mesmo de eu isso em uma classe:

class Tes{
static void nome(){}
void nome(){}

isso nao compila apenas pq mudei o modificador de nivel de acesso da classe… so se eu mudasse o tipo… entao nao o primeiro nao compila.
O segundo compila pq nao problema de eu dizer que na subclasse meu metodo vai ser final ou seja nao vai poder ser subscrito uma subclasse da subclasse que é sub da super.

cuidado com essa expressao, pq private nem herdado é… pertence a classe… entao nao tem nada ver com subscrição private é com relacao a classe… olhe o codigo abaixo…

class Avi{
private void dados(){}
}
class Av extends Avi{
void dados(){}
}

compila normal e nao é uma subscrição do metodo…

bom pessoal eu pensei assim quando vi uma classe desse tipo se eu tiver errado, so corrigir… heh valeu :smiley:

rumo a scjp!

T

O primeiro não compila porque não se pode sobrepor um método estático com outro de instância.

O segundo compila (não há problemas em pôr um “final” neste caso). Só que você não pode fazer o seguinte:

class Bisneto extends Neto {
    void nome() {}
}

porque você estaria tentando sobrepôr um método que é marcado “final”.

CarlosEduardoDantas

cara… volta la e leia meu texto novamente… eu apenas disse que se marcar a classe pai como private, a classe filha pode escrever o metodo com a mesma assinatura que não dará erro de compilacao… eu nao disse que a classe filha herda, tampouco subscreve um metodo private, pelo contrário… eu disse que a classe filha NÃO SUBSCREVE

LPJava

caduengenheiro:
LPJava:

cuidado com essa expressao, pq private nem herdado é… pertence a classe… entao nao tem nada ver com subscrição private é com relacao a classe… olhe o codigo abaixo…

class Avi{
private void dados(){}
}
class Av extends Avi{
void dados(){}
}

compila normal e nao é uma subscrição do metodo…

cara… volta la e leia meu texto novamente… eu apenas disse que se marcar a classe pai como private, a classe filha pode escrever o metodo com a mesma assinatura que não dará erro de compilacao… eu nao disse que a classe filha herda, tampouco subscreve um metodo private, pelo contrário… eu disse que a classe filha NÃO SUBSCREVE

assim se ela nao herda como é que vai subscrever? entao entendi errado… mais foi o que qdo li, o que vc falou que entendi… so nao precisa ficar nervoso por algo tao simples. :smiley:

CarlosEduardoDantas

LPJava:
caduengenheiro:
LPJava:

cuidado com essa expressao, pq private nem herdado é… pertence a classe… entao nao tem nada ver com subscrição private é com relacao a classe… olhe o codigo abaixo…

class Avi{
private void dados(){}
}
class Av extends Avi{
void dados(){}
}

compila normal e nao é uma subscrição do metodo…

cara… volta la e leia meu texto novamente… eu apenas disse que se marcar a classe pai como private, a classe filha pode escrever o metodo com a mesma assinatura que não dará erro de compilacao… eu nao disse que a classe filha herda, tampouco subscreve um metodo private, pelo contrário… eu disse que a classe filha NÃO SUBSCREVE

assim se ela nao herda como é que vai subscrever? entao entendi errado… mais foi o que qdo li, o que vc falou que entendi… so nao precisa ficar nervoso por algo tao simples. :smiley:

exatamente… vc entendeu errado … e não é a primeira vez… uma critica construtiva… não me leve a mal

S

Por que não? Não daria para acessar assim?

Neto n = new Neto();
n.nome(); // método de instância
Neto.nome(); // método da classe

Isso é uma particularidade do Java?

CarlosEduardoDantas

Por que não? Não daria para acessar assim?

Neto n = new Neto();
n.nome(); // método de instância
Neto.nome(); // método da classe

Isso é uma particularidade do Java?

n.nome(); não é metodo de instancia… é uma maneira do java de te tapiar para pensar que é… metodo de instancia é quando nao tem modificador static.

S

Sei disso, mas essa é minha dúvida.
Em outras linguagens, você não consegue chamar um método estático com n.nome(), só Neto.nome().

A pergunta é se existe algum motivo especial para o código não compilar ou se é só decisão de projeto da linguagem.

CarlosEduardoDantas

Schuenemann:
Sei disso, mas essa é minha dúvida.
Em outras linguagens, você não consegue chamar um método estático com n.nome(), só Neto.nome().

A pergunta é se existe algum motivo especial para o código não compilar ou se é só decisão de projeto da linguagem.

sim sim… porém no java podemos chamar metodo/atributo/classe interna estatico dentro de uma variavel de instancia, como se pertencesse a instancia, como vc bem sabe … na minha opiniao isso não é legal porque prejudica a legibilidade, mas tudo bem… é uma boa pegadinha pra prova

qto a sua real pergunta entao, métodos de instancia subscritos tem como finalidade o polimorfismo … metodos estaticos são redefinidos… agora misturar estatico com instancia… seria redefinido ou subscrito?

creio eu que seja um dos motivos de gerar erro de compilacao… é a minha visao do problema… outras serão bem vindas…

LPJava

ai galera, olha essa questao:

public class EnumHash {
enum estacao{
PRIM,VERA,OUT,INVER	}

public static void main(String[] args) {

Set<estacao> es = new HashSet<estacao>();
		es.add(estacao.OUT);
		es.add(estacao.PRIM);
	for(estacao c: es)
	System.out.println(c);

Como vcs acha que é a saida? hehe explica porque… essa ai entra as regras de conjunto e ter atenção que é um HashSet.

:smiley:

ViniGodoy

Supondo claro que você feche as chaves para o código compilar, a saída é
OUT
PRIM

ou

PRIM
OUT

Não dá para saber ao certo pois é um HashSet e a ordem não é garantida.

LPJava

ops esqueci das chaves tirando isso a saida é :
PRIM
OUT

observe ele nao tem uma ordem de iteração mais, meu conjunto é classificado pq enum segue o contrato de equals e hashCode enum implementa o contrato de forma eficiente… entao ele ordena… agora se fosse uma List --ArrayList ele ia imprimir:
OUT
PRIM

ja que o acesso é por indice… e o conjunto nao foi ordenado…

eu tive essa conclusão com esse codigo… seria isso?

ViniGodoy

Acho que não, Camilo.

Adicione todos os elementos no set e daí imprima. Vc vai ver que a saída é:
PRIM
OUT
VERA
INVER

Sair ordenado com PRIM e OUT foi só coincidência.
Nem que os hashCodes fossem ordenados, ainda haveria a possibilidade de um HashMap não devolver os números ordenados.

Só de curiosidade os hashs são:

PRIM: 19770577
VERA: 28117098
OUT: 14978587
INVER: 25669322

LPJava

um interessante entao a saida nao é garantida por se tratar de um hashSet que nao sabemos como ocorre a iteração?

ViniGodoy

Sim, HashSet não tem qualquer garantia de ordem.

O algoritmo que ele usa é, a grosso modo, descrito assim:

Crie um array, de um tamanho qualquer, onde cada índice desse array é uma lista de objetos.
Ao inserir um objeto:
Divida o hashcode desse objeto pelo tamanho do array, e pegue a parte inteira.
Na posição do resultado, adicione esse objeto na lista, se ele já não estiver lá.

Exemplo:
//Criamos um array:
List&lt;Object&gt; array[100] = new List&lt;Object&gt;[100];

//Ao adicionar o elemento de hashcode 2109
int pos = elemento.hashCode() / array.length; //pos = 2109 / 100 = 21;
if (array[pos].contains(elemento))
   return; //Não adicionamos nada

array[pos].add(elemento);

Note que, num hashcode bem implementado, haverá poucas colisões de hash, então a lista de cada posição ficará relativamente vazia.
Caso contrário, a lista pode encher e a performance certamente vai cair.

É claro que na prática é um pouco mais complicado que isso, já que a implementação na realidade se baseia na do Map, prevê o crescimento da lista em caso de colisões de hash, etc...

Mas acho que esse pseudo-código já ajuda a entender como seria um possível HashSet e porque é tão rápido.

Raff

PEssol suponha que eu tenha um metodo assim :

public class Base{
void print(Base e){

System.out.println("Base");
}
}

public Derived extends Base {

static void print(Derived e){

System.out.println("Derived");
}
}

A minha duvida e a seguinte para subscrição de metodo eu marcar um metodo com static, mas para sobrecarga sim ? Qual o efeito disso ? Como eu vou poder chamar o o metodo da classe Derived ?

ViniGodoy

Aí você tem 2 métodos, de assinaturas diferentes.

O primeiro, não estático, que recebe um objeto do tipo Base como argumento.
O segundo, estático, que recebe um do tipo Derived como argumento.

ViniGodoy

Para chamar o método de Derived você faz:

R

Raff, entenda que métodos sobrecarregados têm apenas o nome em comum. Não há nenhuma outra relação especial entre eles. A única “regra” é que, pra ser sobrecarga, eles devem ter o mesmo nome e não podem ter a mesma lista de parâmetros. Tirando isso, tudo que se aplica a um método qualquer aplica-se aos métodos sobrecarregados.

Assim sendo, nesse seu caso, vc nunca conseguirá chamar o método estatico sobrecarregado na subclasse a partir da superclasse, pois o método existe apenas na subclasse e a maneira como vc pode invocá-lo é como qualquer outro método static, seja da forma como o Vini colocou, que é a mais indicada, ou possivelmente instanciando um objeto da subclasse e invocando o método a partir de tal objeto (em ambos os casos passando como argumento uma instancia da subclasse).

[]'s

Raff

Valew Pessoal Dúvida exclarecida !!!

LPJava

se vc mudar o tipo do argumento do metodo e manter o nome… ja era… aconteceu a sobrecarga :smiley: so para completar e ficar mais claro…
flw!!

Raff

Valew ia LPJava :mrgreen:

Criado 30 de outubro de 2007
Ultima resposta 9 de nov. de 2007
Respostas 27
Participantes 10