[RESOLVIDO] Variáveis sem tipo definido em JAVA como no C#

Boa noite pessoal, tudo bem?

Depois de dois anos programando em .NET, eu voltei para o JAVA, e com uma dúvida.
No .NET temos a opção de criar uma variável sem tipo, onde o tipo dela será definido quando for atribuído algum valor a ela. Exemplo:

// o tipo da variável será inteiro por causa do valor atribuído.
var idade = 19;

Gostaria de saber se há alguma funcionalidade no JAVA que suporte isso.
Tentei o mesmo comando na plataforma JAVA, porém não funcionou, “var” nem é uma palavra reservada.

Conto com a ajuda de vocês, obrigado.

Everton.

É natural pegarmos alguns “vícios” de linguagem quando ficamos muito tempo na linguagem A e mudamos para a B.
Eu fiquei muito tempo criando procedures para SQL Server, fui entrar num projeto com MySQL e só Deus sabe como sofri, eu não sabia sair da proc em MySQL só pq ele não deixava eu usar return, coisa que era banal em SQL Server. Também não achei nada parecido com raiserror.
Com isso aprendi que, quando mudamos de linguagem, temos que nos adaptar à nova, tentando nos desvincular dos vícios da anterior.

Mas, a respeito do seu problema, não conheço nada parecido no Java (na verdade nem sabia que exista no C#), o que você pode fazer é criar uma variável do tipo Object e atribuir o valor que você quiser para essa variável, embora o ideal é que você sempre saiba com que tipo de dado você está lidando.

Object a = 4;
Object b = "String qualquer";
Object c = new Abc();
Object d = new ArrayList<Object>();

Mas isso que você fez acima lhe traz um sério problema, se tentar acessar, por exemplo, o método add (presente na interface List) do objeto apontado por d, vc terá esse erro "The method add(String) is undefined for the type Object ". Ou seja, você terá sempre que fazer um cast, algo como…

code.add(“blabla”);[/code] Sendo que isso ainda vai gerar um warning do compilador. Além disso, para fazer essa conversão, você precisa saber o tipo da variável d, coisa que você não sabe, já que a declarou como Object justamente por isso.

Por isso que falei acima que precisamos mudar algumas formas que temos de pensar quando também mudamos de linguagem.

Não existe esse recurso em java.
Você pode, no máximo, driblar essa limitação, seja com um tipo genérico (como o renamed explicou), seja forçando-se a declarar o tipo correto.

Outros recursos do C# que não existem em java são:

  1. LINQ;
  2. Extension Methods;
  3. Delegates;
  4. Generics com tipos primitivos (a implementação de generics dos dois é um bocado diferente);
  5. Lambda (virá nas próximas versões);
  6. yield return;
  7. Sobrecarga de operadores, construtores implícitos e sobrecarga de casting explícita e implícita;
  8. Modificador de acesso “internal”;

E depois os javaboys se surpreendem quando eu digo que prefiro programar em C#.

Obrigado pela resposta pessoal.
Realmente no C#, o tipo “var” as vezes facilita muito quando é necessário armazenar um valor em que não sabemos qual é o seu tipo. Uso muito em foreachs.
O cast na hora de usar a variável Object não facilitaria o processo.
Acho que cada linguagem tem seus altos e baixos, cada uma é boa em alguma coisa.
Enfim, obrigado pelo help que me deram.

Uma coisa que uso bastante em .NET e que sinto falta em Java é o uso de “partial class”.

Definição:

“A partial class, or partial type, is a feature of some object oriented computer programming languages in which the declaration of a class may be split across multiple source-code files, or multiple places within a single file.”

Não sei se o contéudo está correto, mas encontrei este artigo citando a comparação das duas linguagens no wikipedia.

Não entendi bem pq o pessoal falou que nao existe recurso parecido no java. E nao entendi bem pq falaram que usar genericos é “driblar” isso…Sinceramente, é exatamente para isso que os genericos foram criados =/
Após voce atribuir um objeto para uma referencia generica não vai mais haver cast pq aquela referencia agora será exatamente do tipo que voce especificou. Se quiser tirar a prova atribua a uma variavel generica um inteiro e depois faça um if com um instanceof. Sinceramente genericos sao exatamente isso que voce quer.

[quote=carlos.e.a]Não entendi bem pq o pessoal falou que nao existe recurso parecido no java. E nao entendi bem pq falaram que usar genericos é “driblar” isso…Sinceramente, é exatamente para isso que os genericos foram criados =/
Após voce atribuir um objeto para uma referencia generica não vai mais haver cast pq aquela referencia agora será exatamente do tipo que voce especificou. Se quiser tirar a prova atribua a uma variavel generica um inteiro e depois faça um if com um instanceof. Sinceramente genericos sao exatamente isso que voce quer.[/quote]

Na verdade não é.

Ao executar esse código

public class Classe{
	
	public static void main(String[] args) {
		metodo();
	}
	
	public static <G> void metodo(){
		List<String> lista = new ArrayList<String>();
		
		lista.add("aee");
		
		G variavel = lista.get(0); //erro aqui
		System.out.println(variavel);
	}
}

O erro é apresentado:

Type mismatch: cannot convert from String to G

E era exatamente o que nosso amigo queria, um tipo de dado que aceitasse qualquer outro, sem erros. E Generics nao permitiu isso.

Generics é utilizado pelo compilador (não sei se só por ele) para verificar se vc está trabalhando com tipos compatíveis. É justamente a ideia da interface List… criar um objeto genérico (que funcione com qq objeto) desde que ele especifique esse objeto, para evitar do cara embananar o programa inserindo tipos diferentes e sem relação nenhuma na List ou qualquer outra classe que utilize Generics.

Tanto é que esse exemplo funciona, embora com warning de conversão.

public class Classe{
	
	public static void main(String[] args) {
		metodo();
	}
	
	public static <G> void metodo(){
		List<G> lista = new ArrayList<G>();
		
		lista.add((G)"aee");
		
		G variavel = lista.get(0);
		System.out.println(variavel);
	}
}

Posso até ter entendido errado, mas acho que é mais ou menos isso que ele quer:

[code]
public class RetornaGenerico {

    public static <T> T criar(T t){
        return t;
    }

}[/code]

public class UsoGenerics { public static <T> void main(String args[]){ T teste = (T) RetornaGenerico.criar(5); if(teste instanceof Integer){ System.out.println("YES"); } T teste2 = (T) RetornaGenerico.criar("lalala"); if(teste2 instanceof String){ System.out.println("YES"); } } }

Estou enganado?
Voce pode até colocar pra retornar referencias para os objetos diretamente se quiser usar os metodos dos mesmos…

Olá.

Essa seria uma opção, mas com duas ressalvas!

  1. Alguns desenvolvedores não gostam do uso do instanceof. Esse artigo pode explicar melhor. "Anytime you find yourself writing code of the form “if the object is of type T1, then do something, but if it’s of type T2, then do something else,” slap yourself. (Scott Meyers);
  2. Nós continuamos com o problema de ter que fazer cast, veja:
public class UsoGenerics {
	public static <T> void main(String args[]){		
		List<String> lista = new ArrayList<String>();
		
		T teste = (T) RetornaGenerico.criar(lista);
		if (teste instanceof List){
			teste.add("aaa"); //The method add(String) is undefined for the type T
		}
	}
}

class RetornaGenerico {
    
    public static <T> T criar(T t){
        return t;
    }
}

Ao invés, deveríamos escrever:

public class UsoGenerics {
	public static <T> void main(String args[]){		
		List<String> lista = new ArrayList<String>();
		
		T teste = (T) RetornaGenerico.criar(lista);
		if (teste instanceof List){
			((List) teste).add("Aee"); //Cast aqui
		}
	}
}

class RetornaGenerico {
    
    public static <T> T criar(T t){
        return t;
    }
}

Apenas o uso de Generics não resolveria nosso problema, ainda teríamos que fazer cast. E cast tem um pequeno overhead em tempo de execução. Além disso, imagine se nosso amigo tivesse um grande número de possibilidade de objetos a serem testados, ele teria que encher o código de if para saber com que tipo de dado ele está lidando.

Espero ter ajudado =)

Hum…entendi. Mas como que o compilador C++ faz pra determinar o tipo? Ele tambem nao faz um cast?

ps: É eu estava pensando aqui nessa questao do if tambem…poderiam ser muitos e tornar o codigo dificil de manter por exemplo na adicao de novos tipos.

Não, em tempo de compilação ele verifica se o tipo passado é compatível com o texto escrito. Se for, ele cria um novo método, para aquele tipo específico. Sem nenhum tipo de cast.

O var é bem diferente dos generics. Ele faz com que o C# determine o tipo no momento da compilação. Agora, são poucas as situações que o tipo do var é realmente desconhecido. Só quando está se trabalhando com generics, e olha lá.