tags:

views:

234

answers:

10

I'm new to java, and this question struck me. When you instantiate an object, why do you specify the class twice?

OddEven number = new OddEven();

Why can't you just say number = new OddEven();? When I delcare a string, I only say String once:

String str = "abc";

Actually, my question is not "why do you do it this way" -- obviously, you do it because you have to -- but rather, why did the creators choose to make Java syntax work like this?

My thoughts are: 1. There is something fundamental to the way Java operates at a low level that necessitates typing the name twice, or 2. the creators freely choose to do it this way to keep some aspect of the syntax uniform -- declare the type first? Or was it to be more like its predecessors?

+23  A: 

Because you can do this:

Superclass x = new Subclass();

The type of the reference can be a superclass of the actual object being declared, so you need to specify both. For example, you can do:

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

Your program interacts with objects that implement List, and you don't care about the implementation.,

Jim Garrison
To further enhance Jim's (correct) comment - the reason you'd want to use a Superclass is because you can program to the interface. This way, if an ArrayList is a good choice as an interface, but then, later, you find a LinkedList is a better choice, you can switch to a LinkedList without having to change the rest of your application.
JasCav
JDK7 should allow you to write `List<String> stringList = new ArrayList<>();`. It's a small improvement.
Tom Hawtin - tackline
@Tom: Ah yes, I've heard about that -- it's about time :-)
Jim Garrison
A: 

First OddEven is the type, second is the instance. It need not be even OddEven, it could be any subclass of OddEven. It does not mean you have type it twice. Any IDE have code templates where you have to type the name only once.

fastcodejava
Whether you type it or your IDE types it, it's still being typed.
Laurence Gonsalves
A: 

The first declaration is the type of variable you want to use in the scope you have, in this case it is OddEven, the second declaration is the constructor to use for instantiating (and in this case initializing) the reference.

You could have said INumberInstance = new OddEven(), where INumberInstance is some class which OddEven can be cast to (like a super of OddEven for instance).

GrayWizardx
A: 

The way to create a new object in java is:

Class_name reference_variable = new Class_name(param_if_any);

But the string class is an exception.

You can create a new string object as

String s = "abc";

or

String s = new String("abc");
codaddict
+3  A: 

The reason for the seemingly redundant type name is that you are performing two separate operations, each of which requires you to specify a type.

On the left side, you are declaring a variable (a storage location) with a particular type. On the right side, you are creating a new object with a particular type. The '=' in the middle causes a reference to the new object you created to be placed in the storage location you created.

The types on each side do not have to be the same. This, for example, is legal code:

Object number = new OddEven();

The reason that the keyword String only shows up once in your second example is that the type String is implied on the right hand side since "xxx" is a String constant. It is simply shorthand for:

String string = new String("xxx");

Hope this helps!

Steve
Ooops...meant "String string = new String("xxx") in my last line of code above.
Steve
@Steve: fixed it for you
just somebody
A: 

Further to what Jim said, Java is a statically typed language. That means that every varable has a type that is know at compile time.

For instance:

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();
    }
}

the compiler looks at "a.foo()" and "b.foo()" and checks to see that a is of type A and A has a method called "foo" that takes no arguments. The compiler does the same for "b.foo()".

If you could write main like this:

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();
    }
}

then the compiler could not do that verification and it would have to happen at runtime.

TofuBeer
A: 

Think of 'OddEven number' as defining the Object and 'new OddEven();' as filling the object.

I'm not going to get into detail about superclasses and subclasses because other people have explained it already.

Gnarly
A: 

The designers of Java did not have to make the syntax redundant. Scala is another language using the JVM, and it's also statically typed. Scala uses type inferencing to cut out verbosity. For instance here's a declaration of a variable of type MyPair called x. MyPair associates two variables with each other. It's a generic class, so you can specify that the first variable have type Int and the second the type String:

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

Scala type inferencing lets you remove the redundant type declaration:

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

And Scala even infers types based on the constructor arguments, so you can write it this way:

var x = new MyPair(1, "scala")
Jim Ferrans
+1  A: 

When you write:

OddEven number = new OddEven();

You actually do two things : 1) you declare a variable number of type OddEven and 2) you assign a reference to a new instance of class OddEven. But because a variable can hold any subtype of a type, writing number = new OddEven(); wouldn't be enough for the compiler to know the real type of the number variable. So, you have to declare it too. Java is a strongly typed language, which means that every variable and every expression has a type that is known at compile time. You may want to read the whole Chapter 4. Types, Values, and Variables of the Java Language Specification (JLS) to learn more on this.

Now, when your write:

String str = "abc";

Things are a bit different. Characters enclosed in double quotes, "abc" here, are called a string literal which is already a reference to an instance of String and always refers to the same instance of class String. Quoting the section 3.10.5 String Literals of the JLS:

Each string literal is a reference (§4.3) to an instance (§4.3.1, §12.5) of class String (§4.3.3). String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions (§15.28)-are "interned" so as to share unique instances, using the method String.intern.

So, String str = "abc"; is certainly not converted into String str = new String("abc"); which is absolutely not equivalent as I've read in some comments and answers. Running the following class:

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);
    }
}

Produces the output below:

true
false

And demonstrates that one and two are references to the same instance but that abc is a reference to another instance (i.e. an extra unnecessary object has been created).

Actually, using new String(String) is a inefficient way to construct new strings and should only be used to force a substring to copy to a new underlying character array, as in

String tiny = new String(monster.substring(10,20))
Pascal Thivent
A: 

When you say String name = "foo", internally Java compiler creates a String object with the value "foo" and it assigns its reference to name variable. So, here instead of creating a new String object, we are assigning a reference to the other String object.

Btw, the compiler anyway creates "foo" for us. It first looks in String Pool, if it not exists, only then it creats "foo". Otherwise, Compiler returns a reference from String pool. This is some optimization that Java compiler performs internally.

String name = "foo" is simlar to OddEvenNumber oddEven = anotherOddEvenObject;

Veera