Desenvolvedores de C # aprendendo Java, quais são as maiores diferenças que alguém pode ignorar? [fechadas]

87

Para desenvolvedores c # que estão começando a aprender Java, existem grandes diferenças subjacentes entre as duas linguagens que devem ser apontadas?

Talvez algumas pessoas possam presumir que as coisas sejam iguais, mas há alguns aspectos importantes que não devem ser negligenciados? (ou você pode realmente estragar tudo!)

Talvez em termos de construções OOP, a forma como o GC funciona, referências, implantação relacionada, etc.

mrblah
fonte

Respostas:

122

Algumas pegadinhas na minha cabeça:

  • Java não tem tipos de valor personalizados (structs), então não se preocupe em procurá-los
  • Enums Java são muito diferentes da abordagem de "números nomeados" do C #; eles são mais OO. Eles podem ser usados ​​com grande efeito, se você for cuidadoso.
  • byte é assinado em Java (infelizmente)
  • Em C #, os inicializadores de variáveis ​​de instância são executados antes do construtor da classe base; em Java, eles são executados depois disso (ou seja, logo antes do corpo do construtor em "esta" classe)
  • Em C #, os métodos são lacrados por padrão. Em Java, eles são virtuais por padrão.
  • O modificador de acesso padrão em C # é sempre "o acesso mais restritivo disponível no contexto atual"; em Java é acesso de "pacote". (Vale a pena ler sobre os modificadores de acesso específicos em Java.)
  • Os tipos aninhados em Java e C # funcionam de maneira um pouco diferente; em particular, eles têm restrições de acesso diferentes e, a menos que você declare o tipo aninhado como sendo, staticele terá uma referência implícita a uma instância da classe contida.
Jon Skeet
fonte
5
+1 Esta é uma ótima lista para começar.
Jim Schubert
3
@Jon Skeet: +1, E você provavelmente sentiria falta do Lambda e do LINQ até o Java 7?
Kb.
1
"Em C #, os inicializadores de variável de instância são executados antes do construtor da classe base; em Java, eles são executados depois disso (ou seja, logo antes do corpo do construtor" nesta "classe)" - Eeer, você poderia elaborar isso? Não tenho certeza se realmente entendi o que você está dizendo :)
cwap
7
@cwap: Em C #, a ordem de execução é "inicializadores de variável de instância, construtor de classe base, corpo do construtor". Em Java é "construtor de superclasse, inicializadores de variável de instância, corpo do construtor". (Inicializadores de variável de instância são o que você obtém quando atribui um valor a uma variável de instância no ponto de declaração.)
Jon Skeet
1
@cwap: Sim, é o que quero dizer - o último é um inicializador de objeto .
Jon Skeet
17

Estou surpreso que ninguém tenha mencionado propriedades, algo bastante fundamental em C #, mas ausente em Java. C # 3 e acima também implementaram propriedades automaticamente. Em Java, você deve usar métodos do tipo GetX / SetX.

Outra diferença óbvia são as expressões LINQ e lambda em C # 3 ausentes em Java.

Existem algumas outras coisas simples, mas úteis, ausentes em Java, como strings verbatim (@ ""), sobrecarga de operador, iteradores usando rendimento e pré-processador também estão ausentes em Java.

Um dos meus favoritos pessoais em C # é que os nomes de namespace não precisam seguir a estrutura de diretório físico. Eu gosto muito dessa flexibilidade.

softveda
fonte
10

Existem muitas diferenças, mas estas me vêm à mente:

  • Falta de sobrecarga de operador em Java. Observe sua instância.Equals (instância2) versus instância == instância2 (especialmente com strings).
  • Acostume-se com interfaces que NÃO têm o prefixo I. Freqüentemente, você vê namespaces ou classes com o sufixo Impl.
  • O bloqueio verificado duas vezes não funciona por causa do modelo de memória Java.
  • Você pode importar métodos estáticos sem prefixá-los com o nome da classe, o que é muito útil em certos casos (DSLs).
  • As instruções switch em Java não requerem um padrão e você não pode usar strings como rótulos de maiúsculas e minúsculas (IIRC).
  • Os genéricos Java irão irritá-lo. Os genéricos Java não existem em tempo de execução (pelo menos no 1.5), eles são um truque do compilador, o que causa problemas se você quiser fazer uma reflexão sobre os tipos genéricos.
Sneal
fonte
4
A última vez que verifiquei, as strings NÃO sobrecarregaram == e também não ouvi falar que elas foram adicionadas ao Java 7. Eles, no entanto, sobrecarregam + para concatenação de strings.
Michael Madsen
3
Sim, comparar strings com == é uma armadilha muito comum para iniciantes. .equalsé o que você tem que usar.
Michael Myers
Além disso, não entendo o comentário sobre métodos estáticos. Quase todas as linguagens não permitem métodos estáticos ou o equivalente?
Michael Myers
Quase votei a favor, mas discordo sobre os genéricos. Eu gosto do apagamento de tipo.
finnw
2
"As instruções de switch em Java não exigem um padrão" - nem o C #.
RenniePet
8

.NET reificou genéricos; Java apagou os genéricos.

A diferença é esta: se você tem um ArrayList<String>objeto, em .NET, você pode dizer (em tempo de execução) que o objeto tem tipo ArrayList<String>, enquanto em Java, em tempo de execução, o objeto é do tipo ArrayList; a Stringparte está perdida. Se você colocar não- Stringobjetos no ArrayList, o sistema não poderá forçar isso, e você só saberá sobre isso depois de tentar extrair o item e o elenco falhar.

Chris Jester-Young
fonte
1
... embora valha a pena acrescentar que você não pode colocar não- Stringobjetos nessa lista sem fazer uma conversão não verificada, em algum lugar , e o compilador irá avisá-lo corretamente naquele ponto que o compilador não pode mais verificar os limites genéricos. Contanto que sua lista esteja sempre armazenada em uma variável de List<String>, as tentativas de inserir um objeto não String nela não serão compiladas.
Andrzej Doyle
"non-String objetos no ArrayList, o sistema não pode impor que": Note-se que o sistema faz aplicá-la em tempo de compilação. No entanto, você pode contornar isso lançando (ou não usando genéricos); então, a verificação de tempo de execução o detectará, mas apenas durante a extração.
sleske
1
@Andrzej, @sleske: Estou falando apenas sobre o tempo de execução. Digamos que você obtenha o objeto por meio de reflexão e invoque seu addmétodo (novamente, por meio de reflexão). O sistema rejeitará um não- Stringobjeto imediatamente ou apenas ao lançar o resultado de get?
Chris Jester-Young
@sleske: Mas IIRC você só precisa de uma conversão implícita para contornar a verificação de tipo.
Niki
@Judah: Eu revirei sua mudança (sim, um ano depois do fato), porque você não pode ter objetos do tipo List. Você pode ter objetos de tipos descendentes de List, como ArrayListe LinkedList. (É importante usar em Listvez de ArrayListao distribuí-los, mas não muda o fato de que você não pode dizer new List().)
Chris Jester-Young
6

Uma coisa que sinto falta em C # do Java é o tratamento forçado de exceções verificadas. Em C #, é muito comum que alguém desconheça as exceções que um método pode lançar e você esteja à mercê da documentação ou dos testes para descobri-las. Não é assim em Java com exceções verificadas.

Sean
fonte
1
FWIW, isso foi considerado no desenvolvimento do C # e a justificativa para deixá-los de fora é real. Considere artima.com/intv/handcuffs.html . Não é que os designers se oponham filosoficamente às exceções verificadas - ao contrário, eles estão esperando por uma técnica melhor que ofereça benefícios semelhantes sem todas as desvantagens cabeludas.
Greg D
Sim, sim, um assunto muito contencioso ...
sleske
2
Eu gosto do fato de que C # não tem exceções verificadas, mas esta foi a primeira postagem a apontar a diferença, então +1.
Nick
5

Java possui autoboxing para primitivos em vez de tipos de valor; portanto, embora System.Int32[]seja uma matriz de valores em C #, Integer[]é uma matriz de referências a Integerobjetos e, como tal, não é adequada para cálculos de desempenho superior.

Pete Kirkham
fonte
1
Pete: esse é um ponto excelente, que eu nunca soube ou pelo menos nunca considerei (ser um desenvolvedor C # e novo em Java).
Jim Schubert de
4

Sem delegados ou eventos - você tem que usar interfaces. Felizmente, você pode criar classes e implementações de interface inline, então isso não é um grande negócio

theecoop
fonte
3
"não é um grande negócio". Direito. Porque x => x.Foovs. new Bar() { public void M(SomeType x) { return x.Foo; } }- quem se importa com o código sendo 10 vezes menor?
Kirk Woll
2

A funcionalidade interna de data / calendário em Java é horrível em comparação com System.DateTime. Há muitas informações sobre isso aqui: O que há de errado com a API Java Date & Time?

Algumas delas podem ser dicas para um desenvolvedor C #:

  • A classe Java Date é mutável, o que pode tornar perigoso o retorno e a passagem de datas.
  • A maioria dos construtores java.util.Date estão obsoletos. Simplesmente instanciar uma data é bastante prolixo.
  • Eu nunca fiz a classe java.util.Date interoperar bem com serviços da web. Na maioria dos casos, as datas em ambos os lados foram transformadas descontroladamente em alguma outra data e hora.

Além disso, o Java não tem todos os mesmos recursos que o GAC e os assemblies fortemente nomeados trazem. Jar Hell é o termo para o que pode dar errado ao vincular / fazer referência a bibliotecas externas.

No que diz respeito ao empacotamento / implantação:

  • pode ser difícil empacotar aplicativos da web em um formato EAR / WAR que realmente sejam instalados e executados em vários servidores de aplicativos diferentes (Glassfish, Websphere, etc).
  • implantar seu aplicativo Java como um serviço do Windows exige muito mais esforço do que em C #. A maioria das recomendações que recebi envolvia uma biblioteca terceirizada não gratuita
  • a configuração do aplicativo não é tão fácil quanto incluir um arquivo app.config em seu projeto. Há uma classe java.util.Properties, mas não é tão robusta e encontrar o local certo para descartar seu arquivo .properties pode ser confuso
intoOrbit
fonte
1

Não há delegados em Java. Portanto, além de todos os benefícios que os delegados trazem para a mesa, os eventos também funcionam de forma diferente. Em vez de apenas conectar um método, você precisa implementar uma interface e anexá-la.

BFree
fonte
1

Uma coisa que saltou b / c está na minha lista de entrevistas é que não há nenhuma palavra-chave "nova" análoga em Java para ocultar métodos e, portanto, nenhum aviso do compilador "você deve colocar nova aqui". Ocultação de método acidental quando você pretendia ignorar leads para bugs.

(editar, por exemplo) Exemplo, B deriva de A (usando a sintaxe C #, Java se comporta da mesma forma que verifiquei, mas não emite aviso do compilador). Foo de A é chamado, ou foo de B? (A é chamado, provavelmente surpreendendo o dev que implementou B).

class A 
{
public void foo() {code}
}

class B:A
{
public void foo() {code}
}    

void SomeMethod()
{
A a = new B(); // variable's type is declared as A, but assigned to an object of B.
a.foo();
}
Jim L
fonte
2
Como você oculta acidentalmente um método de instância em Java? eles são finais - portanto, não há substituição ou newmétodo para ocultar intencionalmente - ou não finais, substituídos em vez de ocultos.
Pete Kirkham
Exemplo adicionado. Eu não testei em Java há algum tempo, mas a pergunta da entrevista veio originalmente do grupo Java da minha empresa anterior. Em C #, o aviso do compilador geralmente significa que as pessoas mudam o nome. Eu admito que é um caso muito estranho, mas OP parecia estar pedindo coisas que seriam potencialmente difíceis de encontrar problemas ao trocar de idioma.
Jim L
1
A diferença aqui é que em Java todos os métodos são virtuais (então em Java, será B.foo () que será chamado porque Java sempre faz despacho de método dinâmico), enquanto em C # os métodos não são virtuais por padrão (e A.foo () seria chamado). Muitos verificadores de estilo de codificação para Java dirão que B deve usar a anotação @Override.
William Billingsley
1

Java não tem LINQ e a documentação é um inferno. As interfaces de usuário em Java são difíceis de desenvolver, você perde todas as coisas boas que a Microsoft nos deu (WPF, WCF, etc ...), mas se torna difícil de usar, dificilmente documentadas "APIs".

Turing Completo
fonte
0

O único problema que encontrei até agora ao trabalhar com Java vindo do C # é que exceções e erros são diferentes.

Por exemplo, você não pode detectar um erro de falta de memória usando catch (Exceção e).

Consulte o seguinte para obter mais detalhes:

why-is-java-lang-outofmemoryerror-java-heap-space-not-locked

Chris Persichetti
fonte
É intencionalmente projetado dessa forma para desencorajar o programador de aplicativos de pegá-lo
finnw
Sim, tenho certeza que sim, mas vindo do lado C #, onde tudo o que você precisa se preocupar é em detectar exceções, me deixou confuso :)
Chris Persichetti
0

Já faz muito tempo desde que estou em Java, mas as coisas que percebi logo de cara no desenvolvimento de aplicativos foram o modelo de evento C #, arrastar e soltar C # vs usar gerenciadores de layout no Swing (se você estiver fazendo desenvolvimento de aplicativos) e tratamento de exceção Java certificando-se de capturar uma exceção e C # não é obrigatório.

Jason Too Cool Webs
fonte
0

Em resposta à sua pergunta muito direta em seu título:

"Desenvolvedores C # aprendendo Java, quais são as maiores diferenças que alguém pode ignorar?"

R: O fato de Java ser consideravelmente mais lento no Windows.


fonte
4
Eu executo o OpenSuSE de 64 bits e o Windows 7 de 64 bits, e o Eclipse IDE é ("parece") mais rápido no Windows. A sua resposta é baseada na observação pessoal ou em benchmarks reais?
Jim Schubert de
0

A diferença mais dolorosa para mim quando mudo para java é a declaração de string.

em C # string(na maioria das vezes) em JavaString

É bem simples, mas acredite em mim, te faz perder muito tempo quando você tem o hábito de snão perder S!

iChaib
fonte