10+ Reasons why Java needs C#’s property syntax
Written in response, to all the Java developers who claim that Java doesn’t need C#’s property syntax.
The truth is most C# developers can’t quantify all the benefits to C# properties because there are so many. Most arguments I have seen from C# developers have been weak at best. These arguments fail to provide the Java development team a good enough reason to implement C#-like properties.
A proper analogy would be the Pyramids. You can’t point to one brick and say, “That brick makes the pyramid,” because every brick is small (relative the size of the who pyramid), but together, each brick is important to making the pyramid and altogether, they are one of the seven wonders of the world. Similarly, C# Properties provide many little features that together improve the language far more significantly than most can’t quantify.
Properties are quite awesome and provide some great features that Java cannot do now.
1. Easy refactoring when moving from a simple member variable to a property.
Properties using the same syntax as a member variable enable more than one feature, but we are going to talk about only this feature here to start.
public class MyObj { public int Id; public String Name; }
The program starts off with this because for years simplicity is all that is needed.
Note: A getter and a setter provide little to no benefit for a model object. If you aren’t encapsulating code on get and set, using a getter and setter gets in the way. Also, a using a getter and a setter is only a convention anyway, and not forced by the language. As such, getters and setters can’t be relied upon.
A year later, you find that you need to add some feature on name set. You change your class. In Java, you have to create getters and setters.
public class MyObj { public int id; private String _Name; public String getName(){return _Name;} public void setName(string value) { _Name = value; // More work here } }
Now every single line of code that calls MyObj.Name is broken. However, with properties, this wouldn’t the case.
public class MyObj { public int id; private String Name { get { return _Name; } set { _Name = value; // more work here } } }
None of my existing code broke using the property example. This sounds trivial but what if you are an API that hundreds of other tools consume and use. Now this a breaking change that has a massive impact on a business. This feature is huge.
Can Java change a class today from a member variable to a method without breaking an API? No, it cannot. Does this happen often? No, but when it does, it is a breaking change without properties, while with properties, it works without a second thought.
Important: This feature is also why so many hacks that suggest that Java adds a language construct that creates getProperty and setProperty methods are still broken. I’ve seen recommendations such as this where the suggestion is for the compiler and IntelliSense to just convert these to getProperty and setProperty:
public class MyObj { @get @set String Name; public MyObj() { setName("Rhyous");// Default value } }
That syntax doesn’t solve the problem. In order to solve this problem, the syntax still has to be this:
public class MyObj { @get @set String Name; public MyObj() { Name = "Rhyous";// Default value } }
However, even with this, the suggested syntax is not the right suggestion. While the above syntax works for auto properties, how would code be added to the get or set method? The above syntactical sugar, while better than what java has now, is lacking compared to C#’s implementation and would result in fewer features.
2. Replacing an object that uses member variables with an interface
This is similar to #1. You have an object and need to create a layer of abstraction and use an interface for that object. But the object uses only member variables? How can you create an interface for the following syntax in Java?
MyObj.Name
You can’t. So to add a layer of abstraction, you now have to first refactor code. Again, as mentioned in #1, moving from MyObj.Name to MyObj.getName() and MyObj.setName() is a breaking change, especially in a API. It can have a massive impact.
Now, before you argue that you would never need to add a layer of abstraction for a simple object, let me remind you that all objects are not simple. I agree, on a simple model object, abstraction wouldn’t be necessary. However, the problem is certainly with a method on an object that also has public members. But you need the whole object, not just the method. And interface with only methods won’t be enough.
MyObj.Name MyObj.CallServer();
Well, we can’t use the CallServer() method as is in a Unit Test. We need to use and interface and dependency injection and good language architecture. We have to refactor some. But we with properties we don’t need to make a breaking change. Without properties, we do. We have to change from MyObj.Name to MyObj.getName().
3. Properties are different than member variables and methods and reflection reflects that.
C# has reflection. You can loop through all members, properties, and methods separately. In Java, you have something similar. But no way to get properties separate from other methods.
When you only want to loop through getters and setters in Java, how do you do that? Unless every getter and setter is perfectly named getProperty setProperty and none of the methods that are not getters or setters have the format of getSomething setComething, you can’t.
Can you loop through only properties today in Java? Maybe. Java cannot guarantee this ability.
4. Sharing objects between Java and C#.
This feature goes beyond properties, but the lack of a Property syntax is the biggest barrier.
In order to do this today, the object has to be written in Java and C#. C# developers have to live with the more verbose getProperty() setPropert() syntax. For example: MyObj.Id++ is nice and clean but the equivalent in java is MyObj.setId(MyOjb.getId() + 1);
Some tools, such as Hibernate/NHibernate, would benefit greatly from this feature.
5. Properties let you write with cleaner and shorter syntax.
You save programming time. You save lines of code. Look below, as three lines become one.
private String _Name; public String getName() { return _Name; }; private void setName(String name) { _Name = name; }
vs
public string Name { get; set; }
Java is not just a little more typing, it is a lot more typing. While you can argue that snippets or IDE code generator tools take care of this, I’d argue that C# has snippets and code generators, too. I can type prop tab in Visual Studio and have property pretty quickly so at best, snippets help Java almost catch up in development speed.
Also, let’s not forget that this is one single feature. I could write a whole article about all the ways that C#’s property syntax is cleaner and shorter than Java’s syntax.
How about adding one to an int?
MyObj.Id++;
vs in Java
MyObj.setId(MyObj.getId() + 1);
Again, a shorter and simpler syntax probably is a few dozen features as it will be used in so many different ways for so many different language benefits, not just one.
6. Most the property data is in one place.
This provides multiple features:
- Easier to rename
- Easier to copy and paste
- Easier to identify as a property
public string Name { get; set; } [csharp] And in C#, a new syntax was added to make it so you no longer need to break this out to a backing field to set a default value. [csharp] public string Name { get; set; } = "Rhyous";
In java, there is no guarantee that properties are all together. I have seen code like this where the properties are not together in java.
public class MyObj { // Members private Integer _Id; private String _Name; // Getters public Integer getId() { return _Id; }; public String getName() { return _Name; }; // Setters public void setId(int id) { _Id = id; }; public void setName(String name) { _Name = name; } }
While this is fine, it makes renaming have to occur in 7 places in three lines that are separated and could be anywhere in the class file. (Count all the times Name or Id is used and it is 7 times.) In C#, it is once with an auto property and only four times with a property with a backing field. Of course, C# has the same problem once you use a backing field. The backing field isn’t always together with the property, that is only two items that can be separate, not three. In Java, keeping it together would have to be by convention. I use this convention in C# to keep backing fields together.
public string Name { get {return _Name; } set {_Name = value;} } private string _Name;
7. In Aspect-oriented programming (AOP), you can inject code into only Properties.
Using tools like AspectJ, can you do a pointcut only on properties in java? No, you cannot. You can do it on methods and filter it on methods that start with “get” or start with “set”, but we all know that get and set are only conventions and so any method that doesn’t follow convention won’t get the injected code (point cut in AspectJ), and worse, methods that aren’t getters or setters but start with get or set might get the pointcut, which is undesired.
8. Names of properties in a class match when doing Xml or Json serialization
Xml and Json serialization are very common. In C#, for newly developed code, there is no need to decorate the code with any C# Attributes as the names will serialize to JSON and Xml as is.
Imagine we want to get this following Xml from code.
<Person> <FirstName>Jared</FirstName> <LastName>Barneck</LastName> </Person>
Or the following JSON.
{ "FirstName":"Jared", "LastName":"Barneck" }
In C#, we create this poco class. Note: Poco = plain old class object.
public class Person { public string FirstName { get; set; } public string LastName { get; set; } }
In Java, the class is not so simple. There is not an easy or a guaranteed to work way to do this without a lot more code and without annotations. Here is the same object in Java and what you would have to do to have both getters and setters, private members and serialize using Simple. See my article on Java’s Simple Xml Serialization library.
public class Person { @FirstName private String _FirstName {get;set;} public String getFirstName() { return _FirstName; } public void setFirstName(string value) { _FirstName = value; } @LastName private String _LastName {get;set;} public String getLastName() { return _LastName ; } public void setLastName(string value) { _LastName = value; } }
So in Java, names don’t match, requiring the developer to add a fourth line, an annotation, just to make this work. And this is new code, not legacy code.
So when Java developers tell me that they don’t need properties, they are saying that they prefer four lines of code per property over one line per property when doing serialization. There is no argument. Of the two serializable class syntaxes above, C# is the winner by a long way.
Now some serializers other than Simple are made by using magic strings, where they hope that the get and set convention is used and if it is used, everything after the get or set is serialized. So getPerson() will serialize to Person. Still, this leaves the names not matching, and it requires magic strings of “get” and “set” and a hope (or requirement) that convention was followed.
C# also allows for taking of property of one name and serializing it to another name.
public class Person { [XmlElement("fName")] public string FirstName { get; set; } [XmlElement("lName")] public string LastName { get; set; } }
Yes, both C# and Java have this feature. The difference is, this is only needed to accommodate existing or legacy systems and not needed for brand new code and systems.
9. Names of properties in a class match when using a database ORM (or CSV or Excel headers)
Ok, this is almost an identical reason as #8, but serialization for JSON and Xml is vastly different than using a database ORM. But the same issue applies. And really Json and Xml are separate reasons and used often, so I could have broken those out into two features instead of one. But let’s not forget that this also benefits Excel output and CSV output as well as database table output. So, yes, this is a big, huge separate feature than serialization.
If you have a table:
CREATE TABLE [dbo].[User] ( [Id] [int] IDENTITY(1,1) NOT NULL, [Username] [nvarchar](255) NULL, [CreateDate] [datetime] NOT NULL, [LastUpdated] [datetime] NULL, [CreatedBy] [int] NOT NULL, [LastUpdatedBy] [int] NULL )
With properties, the naming scheme matches exactly.
public class User { public int Id { get; set; } public string Username { get; set; } public DateTime CreateDate { get; set; } public DateTime LastUpdated { get; set; } public int CreatedBy { get; set; } public int LastUpdatedBy { get; set; } }
That is simple and pretty with the six members making up six lines. What do we do in Java?
public class Person { @Column(name = "Id") private String _Id {get;set;} public String getFirstName() { return _Id ; } public void setFirstName() { _Id = value; } @Column(name = "FirstName") private String _FirstName {get;set;} public String getFirstName() { return _FirstName; } public void setFirstName(string value) { _FirstName = value; } // Sorry, it is too tedious to even type out the rest of the java example, // I would have to create 16 more lines of code for remaining four columns. Ugh!!! }
10. Making convention a language construct and not just a convention
Multiple times, we have mentioned that trying to require the get and set convention and having tools key of magic strings (starts with “get” or starts with “set”) is not really a good practice. The convention cannot be enforced. I will say that Java has done a tremendous job of trying to enforce this convention. But in the end, it is still a questionable practice that keys off of magic strings that are not guaranteed to be there.
However, by implementing simpler properties, the convention goes away. Everyone who wants property features gets them. Tools no longer have to key off of magic strings.
One might argue that in C#, you can still write the Java way, by writing out getProperty() setProperty(Property value) methods, and that using Properties instead of methods is also only a convention. But that is not true and is shortsighted. Properties are properties. Whereas java only has two object members: member variables and methods; C# has three: member variables, properties, and methods. Properties are not just methods. As noted earlier, properties are separate in reflection, in a different list in the object type information. There is a clear and distinct difference between properties and methods and member variables and how they behave in C#. Because of this, magic strings are not needed to execute code.
Don’t just copy, improve too
Salesforce added C# like properties to Apex, their originally java-based language. Only they enhanced the properties by not requiring a separate backing field. In C#, if you call a property from the get, you create an infinite loop. In Apex, any calls to the variable inside the get don’t create an infinite loop. They copy and improved. Java should do the same.
From the Apex documentation on properties:
Apex properties are based on their counterparts in C#, with the following differences:
- Properties provide storage for values directly. You do not need to create supporting members for storing values.
- It is possible to create automatic properties in Apex. For more information, see Using Automatic Properties.
This is outdated information as C# has had the second item, auto properties, for many years now. However, C# doesn’t have the first improvement yet. Good job Salesforce and Apex. They didn’t just see a good thing and copy it, they saw it, copied it, and improved on it.
Properties Provide More Features
The benefits are many and far more valuable than Java developers or even most C# developer realize. The Pyramid analogy is really accurate. There are so many little features of C# properties that the sum of the feature set is, like sum of bricks in a pyramid, huge.
I surely missed many such features that properties provide.
What features do properties give you that would benefit the Java language?
What shorter syntaxes do properties give you over Java’s getter setter syntax?
Your java classes for serialization/orm are incorrect in two ways: using a C# style propery for the backing field, and using _FirstName instead of _LastName int the getter.
1. Style is not "incorrect." It is a choice.
2. Fixed the second issue. Obviously, this was a copy and paste error in an example project.