Like this one? http://weblogs.asp.net/dwahlin/archive/2007/09/09/c-3-0-features-object-initializers.aspx
Person p = new Person()
{
FirstName = "John",
LastName = "Doe",
Address = new Address()
{
Street = "1234 St.",
City = "Phoenix"
}
};
While both C and C++ may sound similar, their features and usage are different. C is a procedural programming language and does not support objects and classes. C++ is an enhanced version of C programming with object-oriented programming support.
noun plural c's, C's or Cs. the third letter and second consonant of the modern English alphabet. a speech sound represented by this letter, in English usually either a voiceless alveolar fricative, as in cigar, or a voiceless velar stop, as in case.
C+ (grade), an academic grade. C++, a programming language. C with Classes, predecessor to the C++ programming language. ANSI C, a programming language (as opposed to K&R C)
Actually, there is!
Person p = new Person()
{{
setFirstName("John");
setLastName("Doe");
setAddress(new Address()
{{
setStreet("1234 St.");
setCity("Phoenix");
}});
}};
or even:
Person p = new Person()
{{
firstName = "John";
lastName = "Doe";
address = new Address()
{{
street = "1234 St.";
city = "Phoenix";
}});
}};
This is called double brace initialization. However I would avoid this idiom as it has some unexpected side-effects, e.g. this syntax actually creates an anonymous inner class Person$1
and Address$
.
Others have shown the "double brace" initializers, which I think should be avoided - this isn't what inheritance is for, and it will only work as shown when the fields are directly visible to subclasses, which I'd also argue against. It's not really the same thing as C# initializer blocks. It's a hack to take advantage of a language feature designed for other purposes.
If you have more values than you wish to pass to a constructor, you might want to consider using the builder pattern:
Person person = Person.newBuilder()
.setFirstName("John")
.setLastName("Doe")
.setAddress(Address.newBuilder()
.setStreet("...")
.setCity("Phoenix")
.build())
.build();
This also allows you to make Person
immutable. On the other hand, doing this requires the Person
class to be designed for this purpose. That's nice for autogenerated classes (it's the pattern that Protocol Buffers follows) but is annoying boiler-plate for manually-written code.
Normally we use constructors in java to such cases
by using a constructor in the class which you want to create an object you can use that to pass the arguments at the object creating step,
ex- MyData obj1 = new MyData("name",24);
for this case you have to use parameterized constructor matching to the arguments you pass from the main method
Ex-
MyData(String name, int age){
this.name=name;
this.age=age;
}
The full code as follows
class MyData{
public String name;
public int age;
MyData(String name, int age){
this.name=name;
this.age=age;
}
public static void main(String args[]){
MyData obj1 = new MyData("name",24);
}
}
Since double curly braces are generally avoided, you can create a very simple and generic sort of "builder" class that can set properties in a somewhat idiomatic way.
Note: I call the class "Bean" or POJO to follow the javabean standard: What is a JavaBean exactly?. I would primarily use this class to init javabeans anyway.
Bean.java
public class Bean<T> {
private T object;
public Bean(Supplier<T> supplier) { object = supplier.get(); }
public Bean(T object) { this.object = object; }
public T set(Consumer<T> setter) {
setter.accept(object);
return object;
}
}
Instances of this Bean class can be created from an existing object or generated using a Supplier. The object is stored in the the field object
. The set method is a higher-order function that takes in another function--Consumer<T>
. Consumers take in one argument and return void. This will create the setter side-effects in a new scope.
The Bean .set(...)
method returns object
that can be used directly in an assignment.
I like this method because the object's assignment are contained within closed blocks and it feels like I'm setting properties before the object is created rather than than creating the object and mutating it.
The end result is a decent way to create new java objects but this is still a little wordy from the C# object initializer sigh.
And here is the class in use:
// '{}' creates another scope so this function's scope is not "polluted"
// '$' is used as the identifier simply because it's short
Rectangle rectangle = new Bean<>(Rectangle::new).set($ -> {
$.setLocation(0, 0);
$.setBounds(0, 0, 0, 0);
// set other properties
});
if you have nested items, it might be a better to name the variables accordingly. Java doesn't let you use reuse $
because it exists in the outer scope and there is no shadowing.
// this time we pass in new Rectangle() instead of a Supplier
Rectangle rectangle3 = new Bean<>(new Rectangle()).set(rect-> {
rect.setLocation(-50, -20);
// setBounds overloads to take in another Rectangle
rect.setBounds(new Bean<>(Rectangle::new).set(innerRect -> {
innerRect.setLocation(0, 0);
innerRect.setSize(new Bean<>(Dimension::new).set(dim -> {
dim.setSize(640, 480);
}));
}));
});
now compare the normal code
// innerRect and dimension are part of the outer block's scope (bad)
Rectangle rectangle4 = new Rectangle();
rectangle4.setLocation(-50, -20);
Rectangle innerRect = new Rectangle();
innerRect.setLocation(0, 0);
Dimension dimension = new Dimension();
dimension.setSize(640, 480);
innerRect.setSize(dimension);
rectangle4.setBounds(innerRect);
Alternatively, you could have a lambda that takes in void and returns your object and cast it as a Supplier<DesiredType>
and immediately invoke .get()
. This doesn't require a separate class but you have to create bean yourself.
Rectangle rectangle5 = ((Supplier<Rectangle>)() -> {
Rectangle rect = new Rectangle();
rect.setLocation(0, 0);
return rect;
}).get();
A note on practicality: Because you can't reuse $
when nesting elements, this method still tends to be a bit wordy. The variable names start getting long and the any syntax appeal goes away.
It can also be easy to abuse the set() method to create instance of objects within the closure. To use correctly, the only side affects should be on the object you're creating.
One more note: this is really just for fun. Don't ever use this in production.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With