2009-12-24 7 views
11

Cuando crea una instancia de un objeto, ¿por qué especifica la clase dos veces?¿Por qué nombras la clase dos veces durante la creación de instancias en Java?

OddEven number = new OddEven(); 

Por qué no puedes simplemente decir number = new OddEven();? Cuando declaro una cadena, sólo digo una vez String:

String str = "abc"; 

En realidad, mi pregunta no es "¿por qué lo haces de esta manera" -, obviamente, lo haces porque tienes que - sino más bien, ¿Por qué los creadores eligieron hacer que la sintaxis de Java funcionara así?

Mis pensamientos son:

  1. Hay algo fundamental para la manera de Java funciona a un nivel bajo que requiere escribir el nombre dos veces, o
  2. Los creadores eligen libremente a hacerlo de esta manera a mantener un poco aspecto de la sintaxis uniforme - declare el tipo primero? ¿O sería más como sus predecesores?
+1

El ejemplo de la cadena es interesante, me pregunto si ese es el azúcar semántica del lenguaje que se está haciendo en segundo plano, convirtiendo String str = "abc"; a String str = new String ("abc"); – GrayWizardx

+3

GrayWizardx: No. Siempre obtendrás exactamente el mismo objeto 'String' del mismo literal de cadena (incluso si el literal aparece en diferentes archivos fuente). –

+0

Sí, pero. Tom tiene razón en que obtendrás uno y el mismo objeto 'String', pero ese es un comportamiento específico para la clase String, y solo es posible porque las cadenas son inmutables. Otro ejemplo es 'int [] arr = {10, 20, 30};'. Encuentra lo nuevo. Pero realmente hay uno, la sintaxis de inicialización es solo azúcar sintáctica para que no tenga que escribirla. –

Respuesta

43

porque se puede hacer esto:

Superclass x = new Subclass(); 

El tipo de la referencia puede ser una superclase del objeto concreto que se declaró, por lo que es necesario especificar ambos. Por ejemplo, se puede hacer:

List<String> stringList = new ArrayList<String>(); 

Su programa interactúa con los objetos que implementan la lista, y no se preocupan acerca de la aplicación,

+4

Para mejorar aún más el comentario de Jim (correcto), la razón por la que desea usar una Superclase es porque puede programar en la interfaz. De esta forma, si una ArrayList es una buena opción como interfaz, pero luego, si encuentra que LinkedList es una mejor opción, puede cambiar a LinkedList sin tener que cambiar el resto de su aplicación. – JasCav

+1

JDK7 debería permitirle escribir 'List stringList = new ArrayList <>();'. Es una pequeña mejora. –

+0

@Tom: Ah sí, ya me enteré de eso, ya es hora :-) –

0

Primera OddEven es el tipo, la segunda es la instancia.. No necesita ser par OddEven, podría ser cualquier subclase de OddEven. No significa que lo haya tipeado dos veces. Cualquier IDE tiene plantillas de código donde debe escribir el nombre solo una vez.

+0

Ya sea que lo digite o IDE lo escriba, todavía se está escribiendo. –

0

La primera declaración es el tipo de variable que desea usar en el ámbito que tiene, en este caso es OddEven, la segunda declaración es el constructor que se debe usar para crear instancias (y en este caso inicializar) la referencia.

Podrías haber dicho INumberInstance = new OddEven(), donde INumberInstance es una clase a la que se puede convertir OddEven (como un super de OddEven, por ejemplo).

0

La manera de crear un nuevo objeto en Java es:

Class_name reference_variable = new Class_name(param_if_any); 

Pero la clase cadena es una excepción.

Se puede crear un nuevo objeto cadena como

String s = "abc"; 

o

String s = new String("abc"); 
5

La razón para el nombre del tipo aparentemente redundante es que se está llevando a cabo dos operaciones separadas, cada una de las cuales requiere que se especifica un tipo.

En el lado izquierdo, está declarando una variable (una ubicación de almacenamiento) con un tipo particular.En el lado derecho, está creando un nuevo objeto con un tipo particular. El '=' en el medio provoca una referencia al nuevo objeto que ha creado para colocarlo en la ubicación de almacenamiento que ha creado.

Los tipos en cada lado no tienen que ser iguales. Esto, por ejemplo, es un código legal:

Object number = new OddEven(); 

La razón por la que la palabra clave de cadena sólo aparece una vez en su segundo ejemplo es que el tipo de cadena está implícito en el lado derecho ya que "XXX" es una constante de cadena . Es simplemente una abreviatura de:

String string = new String("xxx"); 
+0

Ooops ... significaba "String string = new String (" xxx ") en mi última línea de código anterior. – Steve

+0

@Steve: se lo arregló –

0

Además de lo que dijo Jim, Java es un lenguaje estáticamente tipado. Eso significa que todos los herederos tienen un tipo que se conoce en tiempo de compilación.

Por ejemplo:

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

public class B 
{ 
    public void foo() { } 
} 

public class Main 
{ 
    public static void main(final String[] argv) 
    { 
     A a = new A(); 
     B b = new B(); 

     a.foo(); 
     b.foo(); 
    } 
} 

el compilador mira "a.foo()" y "b.foo()" y comprobaciones para ver que una es de tipo A y A tiene un método llamado " foo "que no tiene argumentos. El compilador hace lo mismo para "b.foo()".

Si usted podría escribir como estos:

public class Main 
{ 
    public static void main(final String[] argv) 
    { 
     a = new A(); // in Java you would really do Object a = new A(); 
     b = new B(); // in Java you would really do Object b = new B(); 

     a.foo(); 
     b.foo(); 
    } 
} 

entonces el compilador no podía hacer que la verificación y que tendría que ocurrir en tiempo de ejecución.

0

Piense en 'OddEven número' como la definición del Objeto y 'nuevo OddEven();' como llenar el objeto.

No voy a entrar en detalles sobre superclases y subclases porque otras personas ya lo han explicado.

0

Los diseñadores de Java no tienen tienen para hacer que la sintaxis sea redundante. Scala es otro lenguaje que usa JVM y también está tipado estáticamente. Scala usa tipo inferencia para cortar la verbosidad. Por ejemplo, aquí hay una declaración de una variable de tipo MyPair llamada x. MyPair asocia dos variables entre sí. Es una clase genérica, por lo que puede especificar que la primera variable tiene el tipo Int y el segundo el tipo String:

var x: MyPair[Int, String] = new MyPair[Int, String](1, "scala") 

tipo Scala inferencia permite eliminar la declaración de tipo redundante:

var x = new MyPair[Int, String](1, "scala") 

Y Scala incluso infiere tipos en función de los argumentos de constructor, para que pueda escribir de esta manera:

var x = new MyPair(1, "scala") 
4

Cuando se escribe:

OddEven number = new OddEven(); 

que realmente hacen dos cosas: 1) se declara una variable de tipo numberOddEveny 2) se asigna una referencia a una nueva instancia de la clase OddEven. Pero como una variable puede contener cualquier subtipo de un tipo, escribir number = new OddEven(); no sería suficiente para que el compilador conozca el tipo real de la variable number. Entonces, debes declararlo también.Java es un fuertemente tipado lenguaje, lo que significa que cada variable y cada expresión tiene un tipo que se conoce en tiempo de compilación. Es posible que desee leer el Chapter 4. Types, Values, and Variables completo de la Especificación del lenguaje Java (JLS) para obtener más información al respecto.

Ahora, cuando su escritura:

String str = "abc"; 

las cosas son un poco diferentes. Los caracteres entre comillas dobles, "abc" aquí, se llaman cadena literal que ya es una referencia a una instancia de String y siempre se refiere a la misma instancia de la clase String. Citando la sección 3.10.5 String Literals del JLS:

Cada cadena literal es una referencia (§4.3) a una instancia (§4.3.1, §12.5) de la clase String(§4.3.3). String objetos tienen un valor constante. Cuerda literales-o, más generalmente, secuencias que son los valores de constantes expresiones (§15.28) -son "internados" con el fin de compartir únicas casos, utilizando el método de String.intern.

Así, String str = "abc"; ciertamente no es convertida en String str = new String("abc"); el que absolutamente no es equivalente como he leído en algunos comentarios y respuestas. Ejecución de la clase siguiente:

public class Test { 
    public static void main(String[] args) { 
     String one = "abc"; 
     String two = "abc"; 
     String abc = new String("abc"); 

     System.out.println(one == two); 
     System.out.println(one == abc); 
    } 
} 

Produce por debajo de la salida:

true 
false 

y demuestra que one y two son referencias a la misma instancia pero que abc es una referencia a otro instancia (es decir, una se ha creado un objeto extra innecesario).

En realidad, el uso de new String(String) es una forma ineficiente de construir nuevas cadenas y sólo debe ser usado para forzar una subcadena para copiar a un nuevo arreglo de caracteres subyacente, como en

String tiny = new String(monster.substring(10,20)) 
+0

Hay una sutileza en el uso de' new String (String) '; vea http : //stackoverflow.com/a/390854/8946. –

0

Cuando dice String name = "foo", internamente Java el compilador crea un objeto String con el valor "foo" y asigna su referencia a la variable name. Entonces, aquí en lugar de crear un nuevo objeto String, estamos asignando una referencia al otro objeto String.

Btw, el compilador de todos modos crea "foo" para nosotros. Primero se ve en String Pool, si no existe, solo entonces crea "foo". De lo contrario, el compilador devuelve una referencia del grupo de cadenas. Esta es una optimización que el compilador de Java realiza internamente.

String name = "foo" es simlar a OddEvenNumber oddEven = anotherOddEvenObject;

0

Considere el siguiente ejemplo,

podemos especificar el tipo de objeto de la siguiente manera,

List<String> abc; 

En metodo1(), si desea utilizar lista de arreglo que se adapte mejor a sus necesidades, entonces podemos crear una instancia de la siguiente manera,

abc = new ArrayList<String>(); 

En metodo2(), si desea utilizar lista de arreglo Vinculado que se adapte mejor para él requisito entonces podemos crear una instancia como el de la siguiente manera,

abc = new LinkedList<String>(); 

Por lo tanto, la idea es que podemos especificar el tipo de " SuperClass "e instancia con cualquier subclase adecuada para diferentes requisitos como" LinkedList "y" ArrayList "en la operación adecuada de forma dinámica.

Cuestiones relacionadas