The new
keyword in languages like Java, Javascript, and C# creates a new instance of a class.
This syntax seems to have been inherited from C++, where new
is used specifically to allocate a new instance of a class on the heap, and return a pointer to the new instance. In C++, this is not the only way to construct an object. You can also construct an object on the stack, without using new
- and in fact, this way of constructing objects is much more common in C++.
So, coming from a C++ background, the new
keyword in languages like Java, Javascript, and C# seemed natural and obvious to me. Then I started to learn Python, which doesn't have the new
keyword. In Python, an instance is constructed simply by calling the constructor, like:
f = Foo()
At first, this seemed a bit off to me, until it occurred to me that there's no reason for Python to have new
, because everything is an object so there's no need to disambiguate between various constructor syntaxes.
But then I thought - what's really the point of new
in Java? Why should we say Object o = new Object();
? Why not just Object o = Object();
? In C++ there's definitely a need for new
, since we need to distinguish between allocating on the heap and allocating on the stack, but in Java all objects are constructed on the heap, so why even have the new
keyword? The same question could be asked for Javascript. In C#, which I'm much less familiar with, I think new
may have some purpose in terms of distinguishing between object types and value types, but I'm not sure.
Regardless, it seems to me that many languages which came after C++ simply "inherited" the new
keyword - without really needing it. It's almost like a vestigial keyword. We don't seem to need it for any reason, and yet it's there.
Question: Am I correct about this? Or is there some compelling reason that new
needs to be in C++-inspired memory-managed languages like Java, Javascript and C# but not Python?
15 Answers 15
Your observations are correct. C++ is a complicated beast, and the new
keyword was used to distinguish between something that needed delete
later and something that would be automatically reclaimed. In Java and C#, they dropped the delete
keyword because the garbage collector would take care of it for you.
The problem then is why did they keep the new
keyword? Without talking to the people who wrote the language it's kind of difficult to answer. My best guesses are listed below:
- It was semantically correct. If you were familiar with C++, you knew that the
new
keyword creates an object on the heap. So, why change expected behavior? - It calls attention to the fact that you are instantiating an object rather than calling a method. With Microsoft code style recommendations, method names start with capital letters so there can be confusion.
Ruby is somewhere in between Python and Java/C# in it's use of new
. Basically you instantiate an object like this:
f = Foo.new()
It's not a keyword, it's a static method for the class. What that means is that if you want a singleton, you can override the default implementation of new()
to return the same instance every time. It's not necessarily recommended, but it's possible.
-
6The Ruby syntax looks nice and consistent! The new keyword in C# is also used as a generic type constraint for a type with a default constructor.Steven Jeuris– Steven Jeuris2011年02月14日 16:28:28 +00:00Commented Feb 14, 2011 at 16:28
-
3Yes. We won't talk about generics though. Both Java and C#'s version of generics are very obtuse. Not saying C++ is much easier to understand though. Generics really are only useful for statically typed languages. Dynamically typed languages like Python, Ruby, and Smalltalk just don't need them.Berin Loritsch– Berin Loritsch2011年02月14日 17:30:59 +00:00Commented Feb 14, 2011 at 17:30
-
2Delphi has a similar syntax to Ruby, except that constructors are usually (but only bhy convention) called Create (`f := TFoo.Create(param1, param2...)'Gerry– Gerry2011年02月14日 20:16:31 +00:00Commented Feb 14, 2011 at 20:16
-
5From language design perspective, keywords are bad for many reasons, mainly you cannot change them. On the other hand reusing the concept of method is easier, but needs some attention while parsing and analysing. Smalltalk and its kin use messages, C++ and itskin on the other hand keywordsGabriel Ščerbák– Gabriel Ščerbák2011年02月16日 11:10:28 +00:00Commented Feb 16, 2011 at 11:10
-
1It's called an initializer, but it does exist.Berin Loritsch– Berin Loritsch2016年01月30日 17:16:39 +00:00Commented Jan 30, 2016 at 17:16
In short, you are right. The new
keyword is superfluous in languages like Java and C#. Here are some insights from Bruce Eckel who was a member of C++ Standard Committee in 1990s and later published books on Java:
[T]here needed to be some way to distinguish heap objects from stack objects. To solve this problem, the new keyword was appropriated from Smalltalk. To create a stack object, you simply declare it, as in Cat x; or, with arguments, Cat x("mittens");. To create a heap object, you use new, as in new Cat; or new Cat("mittens");. Given the constraints, this is an elegant and consistent solution.
Enter Java, after deciding that everything C++ is badly done and overly complex. The irony here is that Java could and did make the decision to throw away stack allocation (pointedly ignoring the debacle of primitives, which I've addressed elsewhere). And since all objects are allocated on the heap, there's no need to distinguish between stack and heap allocation. They could easily have said Cat x = Cat() or Cat x = Cat("mittens"). Or even better, incorporated type inference to eliminate the repetition (but that -- and other features like closures -- would have taken "too long" so we are stuck with the mediocre version of Java instead; type inference has been discussed but I will lay odds it won't happen. And shouldn't, given the problems in adding new features to Java).
-
2Stack vs Heap... insightful, never would have thought of it.WernerCD– WernerCD2011年02月15日 00:25:07 +00:00Commented Feb 15, 2011 at 0:25
-
1"type inference has been discussed but I will lay odds it won't happen.", :) Well, the development of Java still goes forward. Interesting that this is the only flagship for Java 10 though. The
var
keyword is nowhere close as good asauto
in C++, but I hope it will improve.patrik– patrik2018年06月20日 22:26:44 +00:00Commented Jun 20, 2018 at 22:26
There's two reasons I can think of:
new
distinguishes between an object and a primitive- The
new
syntax is a bit more readable (IMO)
The first is trivial. I don't think it's any harder to tell the two apart either way. The second is an example of the OP's point, which is that new
is sort of redundant.
There could be namespace conflicts, though; consider:
public class Foo {
Foo() {
// Constructor
}
}
public class Bar {
public static void main(String[] args) {
Foo f = Foo();
}
public Foo Foo() {
return Foo();
}
}
You could, without too much stretching of the imagination, easily end up with an infinitely recursive call. The compiler would have to enforce a "Function name same as object" error. This really wouldn't hurt, but it is far simpler to use new
, which states, Go to the object of the same name as this method and use the method that matches this signature.
Java is a very simple language to parse, and I suspect this assists in that area.
-
1How is this any different to any other infinite recursion?DeadMG– DeadMG2011年10月28日 12:37:48 +00:00Commented Oct 28, 2011 at 12:37
-
That's a fairly good illustration of a bad thing that could happen, although the developer that does that would have some serious mental issues.Tjaart– Tjaart2012年10月30日 12:32:38 +00:00Commented Oct 30, 2012 at 12:32
-
Why distinguish objects and primitives?Basilevs– Basilevs2024年07月14日 12:51:03 +00:00Commented Jul 14, 2024 at 12:51
In JavaScript you need it because the constructor looks like a normal function, so how should JS know that you want to create a new object if it wasn't for the new keyword?
Invoking a JavaScript function with the new
operator results in different behavior than invoking a function without the new
operator.
For example:
Date() //Returns a string
new Date() //Returns a Date object
function foo() {};
foo() //Returns `undefined`
new foo() //Returns an empty object
Java, for one, still has the dichotomy of C++: not quite everything is an object. Java has built-in types (e.g., char
and int
) that don't have to be allocated dynamically.
That doesn't mean that new
is really necessary in Java though -- the set of types that don't need to be allocated dynamically is fixed and known. When you define an object, the compiler could know (and, in fact, does know) whether it's a simple value that char
or an object that has to be allocated dynamically.
I'll refrain (yet again) from opining on what this means about the quality of Java's design (or lack thereof, as the case may be).
-
More to the point, the primitive types don't need any constructor call at all – they either are written as a literal, come from an operator, or from some primitive-returning function. You actually also create strings (which are on the heap) without a
new
, so this isn't really the reason.Paŭlo Ebermann– Paŭlo Ebermann2019年09月23日 22:26:43 +00:00Commented Sep 23, 2019 at 22:26
In C# it allows types visible in contexts where they might otherwise be obscured by a member. The allows you to have a property with same name as a its type. Consider the following,
class Address {
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
class Person {
public string Name { get; set; }
public Address Address { get; set; }
public void ChangeStreet(string newStreet) {
Address = new Address {
Street = newStreet,
City = Address.City,
State = Address.State,
Zip = Address.Zip
};
}
}
Note the use of new
allows it to be clear that Address
is the Address
type not the Address
member. This allows a member to have the same name as its type. Without this you would need to prefix the name of the type to avoid the name collision, such as CAddress
. This was very intentional as Anders never liked hungarian notation or anything similar and wanted to C# to be usable without it. The fact it was also familiar was a double bonus.
-
w00t, and Address could then derive from an interface called Address.. only, no it can't. So its not much of a benefit, being able to reuse the same name and decrease from the general readability of your code. So by keeping the I for interfaces, but removing the C from classes, they just created a nasty smell for no practical benefit.gbjbaanb– gbjbaanb2012年10月31日 12:12:25 +00:00Commented Oct 31, 2012 at 12:12
-
I wonder that they don't use "New" instead of "new". Somebody could tell them there are also lowercase letters, which sort of solve this problem.maaartinus– maaartinus2013年10月17日 01:36:44 +00:00Commented Oct 17, 2013 at 1:36
-
All reserved words in C derived languages, such as C#, are lower case. The grammar requires a reserved word here to avoid ambiguity thus the use of "new" instead of "New".chuckj– chuckj2013年10月17日 22:16:36 +00:00Commented Oct 17, 2013 at 22:16
-
@gbjbaanb There is no smell. It is always utterly clear whether you're referring to a type or a property/member or a function. The real smell is when you name a namespace the same as a class. MyClass.MyClassStephen– Stephen2015年05月20日 23:50:25 +00:00Commented May 20, 2015 at 23:50
Interestingly, VB does need it - the distinction between
Dim f As Foo
which declares a variable without assigning it, the equivalent of Foo f;
in C#, and
Dim f As New Foo()
which declares the variable and assigns a new instance of the class, the equivalent of var f = new Foo();
in C#, is a substantive distinction. In pre-.NET VB, you could even use Dim f As Foo
or Dim f As New Foo
- because there was no overloading on constructors.
-
4VB doesn't need the shorthand version, it's just an abbreviation. You can also write the longer version with type and constructor Dim f As Foo = New Foo() . With Option Infer On, which is the nearest thing to C#'s var, you can write Dim f = New Foo() and the compiler infers the type of f.MarkJ– MarkJ2012年10月29日 07:56:10 +00:00Commented Oct 29, 2012 at 7:56
-
2...and
Dim f As Foo()
declares an array ofFoo
s. Oh joy! :-)Heinzi– Heinzi2012年10月30日 12:56:31 +00:00Commented Oct 30, 2012 at 12:56 -
@MarkJ: In vb.net, the shorthand is equivalent. In vb6, it wasn't. In vb6,
Dim Foo As New Bar
would effectively makeFoo
a property that would construct aBar
if it was read while (i.e.Nothing
). This behavior wasn't limited to happening once; settingFoo
toNothing
and then reading it would create another newBar
.supercat– supercat2014年03月13日 04:03:17 +00:00Commented Mar 13, 2014 at 4:03
I like a lot of answers and would just like to add this:
It makes the reading of code easier
Not that this situation would happen often, but consider you wanted a method in the name of a verb that shared the same name as a noun. C# and other language naturally have the word object
reserved. But if it were not then would Foo = object()
be the result of the object method call or would it be instantiating a new object. Hopefully said language without the new
keyword has protections against this situation, but by have the requirement of the new
keyword before the calling of a constructor you allow the existence of a method with the same name as an object.
-
5Arguably, having to know this is a bad sign.DeadMG– DeadMG2011年10月28日 12:11:16 +00:00Commented Oct 28, 2011 at 12:11
-
1@DeadMG: "Arguably" means "I'll argue that until the bar closes"...Donal Fellows– Donal Fellows2012年10月30日 14:39:22 +00:00Commented Oct 30, 2012 at 14:39
There's a lot of vestigial stuff in many programming languages. Sometimes it's there by design (C++ was designed to be as compatible as possible with C), sometimes, it's just there. For a more egregious example, consider how far the broken C switch
statement propagated.
I don't know Javascript and C# well enough to say, but I see no reason for new
in Java except that C++ had it.
-
I think JavaScript was designed to "look just like Java" as much possible, even when it's doing something particularly un-Java-like.
x = new Y()
in JavaScript doesn't instantiate theY
class, because JavaScript doesn't have classes. But it looks like Java so it carries thenew
keyword forward from Java, which of course carried it forward from C++.Tyler– Tyler2011年10月31日 16:05:50 +00:00Commented Oct 31, 2011 at 16:05 -
+1 for the broken switch (in the hope you repair it :D).maaartinus– maaartinus2013年10月17日 01:38:00 +00:00Commented Oct 17, 2013 at 1:38
Interestingly, with the advent of perfect forwarding, non-placement new
isn't required at all in C++ either. So, arguably, it's no longer needed in any of the mentioned languages.
-
4What do you forward to? Ultimately,
std::shared_ptr<int> foo();
will have to callnew int
somehow.MSalters– MSalters2011年11月01日 09:56:21 +00:00Commented Nov 1, 2011 at 9:56 -
It will certainly be required. The way
std::string
andstd::vector
, for example, was designed, is by usingstd::allocator<T>
which is all based onnew
anddelete
.Iman Abdollahzadeh– Iman Abdollahzadeh2023年11月19日 05:07:02 +00:00Commented Nov 19, 2023 at 5:07 -
@MSalters which is true only because
new
already exists. There's no reason to not use saymalloc
or any other allocator instead. In fact that's precisely what Rust does and it doesn't need specialnew
keyword.freakish– freakish2024年07月18日 20:20:15 +00:00Commented Jul 18, 2024 at 20:20 -
@freakish: In C++,
malloc
does not create objects. It allocates uninitialized memory; placement new is the second part. It takes allocated but uninitialized memory, and creates objects. Changing the semantics ofmalloc
is theoretically possible, but C++ by design is backwards compatible with C.MSalters– MSalters2024年07月18日 22:38:05 +00:00Commented Jul 18, 2024 at 22:38 -
@MSalters nothing needs to be changed. All we need is a new template function that wraps malloc. It casts the newly created pointer to
*T
, eventually zeros the memory. Voila, new allocator. With this approach of course constructors have to be removed as well, or rather replaced with normal functions that fill the newly created memory. Again: that's literally what Rust does. Also: what do you mean by backwards compatibility with C? C doesn't have new keyword.freakish– freakish2024年07月19日 06:07:48 +00:00Commented Jul 19, 2024 at 6:07
I'm not sure whether Java designers had this in mind but when you think of objects as recursive records, then you could imagine that Foo(123)
doesn't returns an object but a function whose fixpoint is the object being created (ie. function that would return the object if it's given as argument the object being constructed). And the purpose of new
is to "tie the knot" and return that fixpoint. In other words new
would make the "object-to-be" aware of its self
.
This kind of approach could help formalizing inheritance for example: you could extend an object-function with another object-function and finally provide them with common self
by using new
:
cp = new (Colored("Blue") & Line(0, 0, 100, 100))
Here &
combines two object-functions.
In this case new
could be defined as:
def new(objectFunction) {
actualObject = objectFunction(actualObject)
return actualObject
}
The reason why Python does not need it is because of its type system. Fundamentally, when you see foo = bar()
in Python, it doesn't matter what whether bar()
is a method that is being invoked, a class that is being instantiated, or a functor object; in Python, there is no fundamental difference between a functor and function (because methods are objects); and you could even argue that a class being instantiated is a special case of a functor. Thus, there is no reason to create an artifical difference in what is happening (especially since memory management is so extremely hidden in Python).
In a language with a different typing system, or in which methods and classes are not objects, there is the possibility of a stronger conceptual difference between creating an object and calling a function or functor. Thus, even if the compiler/interpreter does not need the new
keyword, it is understandable that it might be maintained in languages that haven't broken all the boundaries that Python has.
To allow 'nil'.
Along with heap based allocation, Java embraced the use of nil objects. Not just as an artifact, but as a feature. When objects can have a nil state, then you have to separate declaration from initialisation. Hence the new keyword.
In C++ a line like
Person me;
Would instantly call the default constructor.
-
5Um, what's wrong with
Person me = Nil
or havingPerson me
be Nil by default and usingPerson me = Person()
for non-Nil? My point is that it doesn't seem that Nil was a factor in this decision...Andres F.– Andres F.2012年10月30日 13:15:48 +00:00Commented Oct 30, 2012 at 13:15 -
You have a point. Person me = Person(); would work equally well.Kris Van Bael– Kris Van Bael2012年10月30日 23:51:27 +00:00Commented Oct 30, 2012 at 23:51
-
@AndresF. Or even simpler with
Person me
being nil andPerson me()
invoking the default constructor. So you'd always need parentheses in order to invoke anything, and thus get rid of one C++ irregularity.maaartinus– maaartinus2014年08月03日 19:49:43 +00:00Commented Aug 3, 2014 at 19:49
Actually in Java there is a difference when using Strings:
String myString = "myString";
is different from
String myString = new String("myString");
Supposing the string "myString"
has never been used before, the first statement creates a single String object in the String pool (a special area of the heap) while the second statement creates two objects, one in the normal heap area for objects and other in String pool. It is pretty obvious that the second statement is useless in this particular scenario, but is allowable by the language.
This means that new assures that the object is created in that special area of the heap, allocated for normal object instantiation, but there may be other ways of instantiating objects without it; the above one is an example, and there is room left for extensibility.
-
3But this wasn't the question. The question was "why not
String myString = String("myString");
?" (note the absence of thenew
keyword)Andres F.– Andres F.2013年01月29日 21:42:23 +00:00Commented Jan 29, 2013 at 21:42 -
@AndresF. Kind of obvious imho... it is legal to have a method named String that returns a String in a String class and there has to be a difference between calling it and calling the constructor. Something like
class MyClass { public MyClass() {} public MyClass MyClass() {return null;} public void doSomething { MyClass myClass = MyClass();}} //which is it, constructor or method?
Random42– Random422013年01月29日 22:03:41 +00:00Commented Jan 29, 2013 at 22:03 -
3But it's not obvious. First, having a regular method named
String
goes against Java style conventions, so you can just assume any method starting with uppercase is a constructor. And second, if we aren't constrained by Java, then Scala has "case classes" where the constructor looks exactly like I said. So where is the problem?Andres F.– Andres F.2013年01月29日 23:11:29 +00:00Commented Jan 29, 2013 at 23:11 -
2Sorry, I don't follow your argument. You are effectively arguing syntax, not semantics, and anyway the question was about
new
for managed languages. I have shown thatnew
is not at all needed (e.g. Scala doesn't need it for case classes) and also that there is no ambiguity (since you absolutely cannot have a method namedMyClass
in classMyClass
anyway). There is no ambiguity forString s = String("hello")
; it cannot be anything else but a constructor. And finally, I disagree: code conventions are there to enhance and clarify the syntax, which is what you're arguing about!Andres F.– Andres F.2013年01月30日 16:17:44 +00:00Commented Jan 30, 2013 at 16:17 -
1So that's your argument? "Java designers needed the
new
keyword because otherwise Java's syntax would have been different"? I'm sure you can see the weakness of that argument ;) And yes, you keep discussing syntax, not semantics. Also, backwards compatibility with what? If you are designing a new language, such as Java, you are already incompatible with C and C++!Andres F.– Andres F.2013年01月30日 17:51:00 +00:00Commented Jan 30, 2013 at 17:51
In C# new is important to distinguish between objects created on the stack vs. the heap. Frequently we create objects on the stack for better performance. See, when a object on the stack goes out of scope, it disappears immediately when the stack unravels, just like a primitive. There is no need for the garbage collector to keep track of it, and there is no extra overhead of the memory manager to allocate the necessary space on the heap.
-
5unfortunately you're confusing C# with C++.gbjbaanb– gbjbaanb2012年10月31日 12:14:10 +00:00Commented Oct 31, 2012 at 12:14
Explore related questions
See similar questions with these tags.
new
keyword. Of course I want to create a new variable, stupid compiler! A good language would in my opinion have a syntax likef = heap Foo()
,f = auto Foo()
.f
doesn't escape the function, allocate stack space.f
when the enclosing function returns.