Los desarrolladores de C # que están aprendiendo Java, ¿cuáles son las mayores diferencias que uno puede pasar por alto? [cerrado]

87

Para los desarrolladores de C # que quieren aprender Java, ¿hay grandes diferencias subyacentes entre los dos lenguajes que deberían ser señaladas?

Quizás algunas personas asuman que las cosas son iguales, pero ¿hay algunos aspectos importantes que no deben pasarse por alto? (¡O realmente puedes arruinarlo!)

Tal vez en términos de construcciones de OOP, la forma en que funciona GC, referencias, implementación relacionada, etc.

mrblah
fuente

Respuestas:

122

Algunas trampas de mi cabeza:

  • Java no tiene tipos de valores personalizados (estructuras), así que no se moleste en buscarlos
  • Las enumeraciones de Java son muy diferentes al enfoque de "números con nombre" de C #; son más OO. Pueden usarse con gran efecto, si tiene cuidado.
  • byte está firmado en Java (desafortunadamente)
  • En C #, los inicializadores de variables de instancia se ejecutan antes que el constructor de la clase base; en Java se ejecutan después (es decir, justo antes del cuerpo del constructor en "esta" clase)
  • En C #, los métodos están sellados de forma predeterminada. En Java, son virtuales de forma predeterminada.
  • El modificador de acceso predeterminado en C # es siempre "el acceso más restrictivo disponible en el contexto actual"; en Java es el acceso al "paquete". (Vale la pena leer sobre los modificadores de acceso particulares en Java).
  • Los tipos anidados en Java y C # funcionan de manera algo diferente; en particular, tienen diferentes restricciones de acceso y, a menos que declare que el tipo anidado static, tendrá una referencia implícita a una instancia de la clase contenedora.
Jon Skeet
fuente
5
+1 Esta es una gran lista para empezar.
Jim Schubert
3
@Jon Skeet: +1, ¿y probablemente extrañaría Lambda y LINQ hasta Java 7?
Kb.
1
"En C #, los inicializadores de variables de instancia se ejecutan antes que el constructor de la clase base; en Java, se ejecutan después que lo hace (es decir, justo antes del cuerpo del constructor en" esta "clase)". Eeer, ¿podría explicar esto? No estoy seguro de entender realmente lo que estás diciendo :)
cwap
7
@cwap: En C #, el orden de ejecución es "inicializadores de variables de instancia, constructor de clase base, cuerpo del constructor". En Java es "constructor de superclase, inicializadores de variables de instancia, cuerpo del constructor". (Los inicializadores de variable de instancia son lo que obtiene cuando asigna un valor a una variable de instancia en el punto de declaración).
Jon Skeet
1
@cwap: Sí, eso es lo que quiero decir, este último es un inicializador de objeto .
Jon Skeet
17

Me sorprende que nadie haya mencionado propiedades, algo bastante fundamental en C # pero ausente en Java. C # 3 y superior también ha implementado propiedades automáticamente. En Java tienes que usar métodos de tipo GetX / SetX.

Otra diferencia obvia son las expresiones LINQ y lambda en C # 3 ausentes en Java.

Hay algunas otras cosas simples pero útiles que faltan en Java como cadenas textuales (@ ""), sobrecarga de operadores, iteradores que usan rendimiento y preprocesador que también faltan en Java.

Uno de mis favoritos personales en C # es que los nombres de los espacios de nombres no tienen que seguir la estructura del directorio físico. Realmente me gusta esta flexibilidad.

softveda
fuente
10

Hay muchas diferencias, pero estas me vienen a la mente:

  • Falta de sobrecarga de operadores en Java. Mire su instancia Igual (instancia2) versus instancia == instancia2 (especialmente con cadenas).
  • Acostúmbrese a que las interfaces NO tengan el prefijo I. A menudo, verá espacios de nombres o clases con el sufijo Impl.
  • El bloqueo comprobado dos veces no funciona debido al modelo de memoria de Java.
  • Puede importar métodos estáticos sin prefijarlos con el nombre de la clase, lo cual es muy útil en ciertos casos (DSL).
  • Las declaraciones de cambio en Java no requieren un valor predeterminado y no puede usar cadenas como etiquetas de caso (IIRC).
  • Los genéricos de Java te enfurecerán. Los genéricos de Java no existen en tiempo de ejecución (al menos en 1.5), son un truco del compilador, lo que causa problemas si desea hacer una reflexión sobre los tipos genéricos.
Burla
fuente
4
La última vez que verifiqué, las cadenas NO se sobrecargaron ==, y tampoco he oído que se agreguen para Java 7. Sin embargo, sobrecargan + para la concatenación de cadenas.
Michael Madsen
3
Sí, comparar cadenas con == es un error muy común para los novatos. .equalses lo que tienes que usar.
Michael Myers
Además, no entiendo el comentario sobre métodos estáticos. ¿No todos los lenguajes permiten métodos estáticos o equivalentes?
Michael Myers
Casi voté a favor de esto, pero no estoy de acuerdo con los genéricos. Me gusta el tipo de borrado.
finnw
2
"Las sentencias Switch en Java no requieren un valor predeterminado", ni C #.
RenniePet
8

.NET tiene genéricos reificados; Java ha borrado los genéricos.

La diferencia es la siguiente: si tiene un ArrayList<String>objeto, en .NET, puede decir (en tiempo de ejecución) que el objeto tiene tipo ArrayList<String>, mientras que en Java, en tiempo de ejecución, el objeto es de tipo ArrayList; la Stringparte se pierde. Si ingresa no Stringobjetos en el ArrayList, el sistema no puede hacer cumplir eso, y solo lo sabrá después de que intente extraer el elemento y el lanzamiento falle.

Chris Jester-Young
fuente
1
... aunque vale la pena agregar que no puede poner no- Stringobjetos en esa lista sin hacer una conversión sin marcar, en algún lugar , y el compilador le advertirá correctamente en ese punto que el compilador ya no puede verificar los límites genéricos. Siempre que su lista esté siempre almacenada en una variable de List<String>, los intentos de insertar un objeto que no sea String no se compilarán.
Andrzej Doyle
"Objetos que no son String en ArrayList, el sistema no puede hacer cumplir eso": Tenga en cuenta que el sistema lo hace cumplir en tiempo de compilación. Sin embargo, puede evitar esto lanzando (o no usando genéricos); luego, la verificación de tiempo de ejecución lo detectará, pero solo al extraer.
Sleske
1
@Andrzej, @sleske: solo estoy hablando de tiempo de ejecución. Digamos que obtiene el objeto a través de la reflexión e invoca su addmétodo (nuevamente, a través de la reflexión). ¿Rechazará el sistema un no Stringobjeto de inmediato, o solo al emitir el resultado de get?
Chris Jester-Young
@sleske: Pero IIRC solo necesita una conversión implícita para eludir la verificación de tipo.
Niki
@Judah: revoqué tu cambio (sí, un año después del hecho), porque no puedes tener objetos de tipo List. Puede tener objetos de tipos que desciendan de List, como ArrayListy LinkedList. (Es importante usarlo en Listlugar de ArrayListpasarlos, pero no cambia el hecho de que no se puede decir new List()).
Chris Jester-Young
6

Una cosa que extraño en C # de Java es el manejo forzado de excepciones marcadas. En C #, ¿es demasiado común que uno desconozca las excepciones que puede generar un método y que esté a merced de la documentación o las pruebas para descubrirlas? No es así en Java con excepciones marcadas.

Sean
fuente
1
FWIW, esto se consideró en el desarrollo de C # y la razón para dejarlos fuera es real. Considere artima.com/intv/handcuffs.html . No es que los diseñadores se opongan filosóficamente a las excepciones marcadas, sino que esperan una técnica mejor que ofrezca beneficios similares sin todos los inconvenientes.
Greg D
Sí, sí, un tema muy polémico ...
sleske
2
Me gusta el hecho de que C # no tiene excepciones marcadas, pero esta fue la primera publicación que incluso señaló la diferencia, así que +1.
Nick
5

Java tiene autoboxing para primitivas en lugar de tipos de valor, por lo que, aunque System.Int32[]es una matriz de valores en C #, Integer[]es una matriz de referencias a Integerobjetos y, como tal, no es adecuada para cálculos de mayor rendimiento.

Pete Kirkham
fuente
1
Pete: ese es un punto excelente, y uno que nunca supe o al menos nunca consideré (siendo un desarrollador de C # y nuevo en Java).
Jim Schubert
4

Sin delegados ni eventos, debe usar interfaces. Afortunadamente, puede crear clases e implementaciones de interfaz en línea, por lo que esto no es tan importante.

thecoop
fuente
3
"no es tan importante". Derecha. Porque x => x.Foovs. new Bar() { public void M(SomeType x) { return x.Foo; } }- ¿a quién le importa que el código sea 10 veces más corto?
Kirk Woll
2

La funcionalidad de fecha / calendario incorporada en Java es horrible en comparación con System.DateTime. Hay mucha información sobre esto aquí: ¿Qué pasa con la API de fecha y hora de Java?

Algunos de estos pueden ser trucos para un desarrollador de C #:

  • La clase Java Date es mutable, lo que puede hacer que la devolución y el paso de fechas sean peligrosas.
  • La mayoría de los constructores java.util.Date están en desuso. Simplemente instanciar una cita es bastante detallado.
  • Nunca he conseguido que la clase java.util.Date interopere bien con los servicios web. En la mayoría de los casos, las fechas de ambos lados se transformaron enormemente en otra fecha y hora.

Además, Java no tiene todas las mismas características que traen el GAC y los ensamblados con nombre seguro. Jar Hell es el término para lo que puede salir mal al vincular / hacer referencia a bibliotecas externas.

En lo que respecta al empaquetado / implementación:

  • Puede resultar difícil empaquetar aplicaciones web en un formato EAR / WAR que realmente se instalen y ejecuten en varios servidores de aplicaciones diferentes (Glassfish, Websphere, etc.).
  • implementar su aplicación Java como un servicio de Windows requiere mucho más esfuerzo que en C #. La mayoría de las recomendaciones que recibí para esto involucraron una biblioteca de terceros no gratuita
  • La configuración de la aplicación no es tan fácil como incluir un archivo app.config en su proyecto. Existe una clase java.util.Properties, pero no es tan robusta y encontrar el lugar correcto para soltar su archivo .properties puede ser confuso
en órbita
fuente
1

No hay delegados en Java. Por lo tanto, además de todos los beneficios que aportan los delegados, los eventos también funcionan de manera diferente. En lugar de simplemente conectar un método, debe implementar una interfaz y adjuntarla.

BFree
fuente
1

Una cosa que resalta porque está en mi lista de entrevistas es que no hay una "nueva" palabra clave análoga en Java para ocultar métodos y, por lo tanto, ningún compilador advierte "debería poner una nueva aquí". La ocultación accidental del método cuando se pretendía anular conduce a errores.

(editar, por ejemplo) Ejemplo, B deriva de A (usando la sintaxis C #, Java se comporta de la misma manera que la última vez que verifiqué, pero no emite una advertencia del compilador). ¿Se llama al foo de A o al foo de B? (Se llama a A, probablemente sorprendiendo al desarrollador que implementó 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
fuente
2
¿Cómo escondes accidentalmente un método de instancia en Java? son finales, por lo que no hay anulación o newmétodo para ocultar intencionalmente, o no finales, por lo que se anulan en lugar de ocultar.
Pete Kirkham
Ejemplo agregado. No lo he probado en Java por un tiempo, pero la pregunta de la entrevista vino originalmente del grupo Java de mi empresa anterior. En C #, la advertencia del compilador generalmente significa que las personas cambian el nombre. Admito que es un caso bastante extraño, pero OP parecía estar pidiendo cosas que serían potencialmente difíciles de encontrar al cambiar de idioma.
Jim L
1
La diferencia aquí es que en Java todos los métodos son virtuales (por lo tanto, en Java, será B.foo () el que se llame porque Java siempre realiza el envío dinámico de métodos), mientras que en C # los métodos no son virtuales por defecto (y A.foo () se llamaría). Muchos verificadores de estilo de codificación para Java le dirán que B debe usar la anotación @Override.
William Billingsley
1

Java no tiene LINQ y la documentación es un infierno. Las interfaces de usuario en Java son difíciles de desarrollar, se pierden todas las cosas buenas que nos dio Microsoft (WPF, WCF, etc.) pero se vuelven "API" difíciles de usar y apenas documentadas.

Turing completo
fuente
0

El único problema con el que me he encontrado hasta ahora al trabajar con Java procedente de C # son las excepciones y los errores son diferentes.

Por ejemplo, no puede detectar un error de memoria insuficiente utilizando catch (Excepción e).

Consulte lo siguiente para obtener más detalles:

¿Por qué-es-java-lang-outofmemoryerror-java-heap-space-not-capturado

Chris Persichetti
fuente
Está diseñado intencionalmente de esa manera para disuadir al programador de aplicaciones de detectarlo
finnw
Sí, estoy seguro de que lo fue, pero viniendo desde el lado C #, donde todo lo que tienes que preocuparte es atrapar excepciones, me dejó en un bucle :)
Chris Persichetti
0

Ha pasado tanto tiempo desde que estoy en Java, pero las cosas que noté desde el principio en el desarrollo de aplicaciones fueron el modelo de eventos C #, C # arrastrar y soltar frente al uso de Layout Managers en Swing (si está haciendo App Dev) y el manejo de excepciones Java asegurándose de detectar una excepción y C # no es necesario.

Jason Too Cool Webs
fuente
0

En respuesta a su pregunta muy directa en su título:

"Los desarrolladores de C # que están aprendiendo Java, ¿cuáles son las mayores diferencias que uno puede pasar por alto?"

R: El hecho de que Java es considerablemente más lento en Windows.


fuente
4
Ejecuto OpenSuSE de 64 bits y Windows 7 de 64 bits, y Eclipse IDE es ("parece") más rápido en Windows. ¿Su respuesta se basa en observaciones personales o en puntos de referencia reales?
Jim Schubert
0

La diferencia más molesta para mí cuando cambio a Java es la declaración de cadena.

en C # string(la mayor parte del tiempo) en JavaString

Es bastante simple, pero créeme, ¡te hace perder tanto tiempo cuando tienes el hábito de sno hacerlo S!

iChaib
fuente