over 4 years ago

Today, let's discuss something not so serious. After I read "Beyond Java," many years later, I rethink about the Java language. I think that Java puts too much emphasis on the library (J2EE has become a big monster), and ignores the language itself (for example, the auto-closable resource in try-catch in J2SE 7 and the Lambda expression in J2SE 8 are little big-changes to the language itself after the generic and autoboxing in J2SE 5). Java SE 8 has released, and not more than one month (2014/3/18 -> 2014/4/15), Java SE 8 Update 5 also released (the version number jumps fast after Oracle takes charge of Java development). The next version, Java SE 9, is prepared to launch. However, after learned different languages, I hope some language features (not necessarily functional) can be added into the future Java.

The first feature I hope to be added is property. In fact, many languages provide the similar language feature, e.g., Objective C and C#. The property can be accessed like variables. For example, in Code List 1, access the publications of a person by using for(Publication* publication in person.publications), or in Code List 2, change the height of a page by using page.Height = 400. It is not the same as declaring public member data, because a property is consisted of a setter and a getter with access control. Therefore, in Code List 2, the change to the height will notify all handlers (observer pattern) through the setter. And some languages provide default implementation of getters/setters, or mechanism to generate getters/setters automatically, e.g, @synthesize firstName;. Although getters/setters can also be generated automatically with Lombok annotations, that is not a part of the Java language. In addition, I don't like use annotation to generate getters/setters (well, this is a personal preferences).

Code List 1 - The property in Objective C
// In Person.h
@interface Person : NSObject

@property (nonatomic, readonly) NSInteger age;
@property (nonatomic, readonly) NSArray* publications;
@property (nonatomic) NSString* firstName;
@property (nonatomic) NSString* lastName;

@end

// In Person.m
@implementation Person {
    NSMutableArray* _publications;
}

@synthesize firstName;
@synthesize lastName;

- (NSInteger)age {
    NSDate* date = [NSDate date];
    NSCalendar* calendar = [NSCalendar currentCalendar];
    NSDateComponents* components = [calendar components:NSYearCalendarUnit fromDate:self.birthday toDate:now  options:0];
    return [ageComponents year];
}

- (NSArray*)publications {
    return _publications;
}
@end

// In somewhere alse
Person* person = [controller getPerson];
for(Publication* publication in person.publications) {
    // do something
}
Code List 2 - The property in C#
// In Page.cs
public class Page : Drawable {

    /// <summary>
 /// Gets or sets the height of the page
 /// </summary>
 public int Height {
        get { return _height; }
        set {
            _height = value;
            NotifyContentUpdatedEventHandlers();
        }
    }
}

// In somewhere alse
Page page = createEmptyPage();
page.Height = 400;

The second feature is literal data structure declaration. Both JavaScript and Objective C provide this feature, Sometimes, when processing datta, a class with getters/setters is required to process a simple data object -- that is boring. For example, in Code List 3, a company data object is created easily. Yes, in fact, Code List 3 is a feature that Objective C borrowed from JavaScript Object Notation (JSON) as shown in Code List 4. Just use a symbol @ to declare literal data structure, and Java can use the same way! Well, someone can explain why the built-in JSON API only available in J2EE -- client does not need to parse JSON? That is somewhere strange.

Code List 3 - The literal data structure declaration
id company = @{
    @"name": @"Far Far AwayCompany",
    @"address": @"I don't want to know",
    @"foundedOn": @1999,
    @"employees": @[ @"Bill", @"Steve", @"John" ]
};
Code List 4 - JavaScript Object Notation
var company = {
    "name": "Far Far AwayCompany",
    "address": "I don't want to know",
    "foundedOn": 1999,
    "employees": [ "Bill", "Steve", "John" ]
};

The third feature is category. That is my favor feature of Objective C. Category is a way to glue new functions to an existing class, but it is not inheritance because the type is not changed. It is not the same as the partial keyword in C#. The category is very useful to design complicated project. The functionalities of a class can be categoried into different files. For example, the conversion between a POJO (Plain Old Java Object) object and JSON string is the responsibility of the POJO object itself, or someone others?

I would choose the prior one when I was new to the OO language, but after I saw many desings, I prefer the latter. Since an object can be outputted to different formats (JSON or XML), when a new format is required to output, the modification to the class source code againsts the open close principle. Without the source code, modification is impossible. Inheritance can add new functions, but the type is changed. With category, the implementation of the new format output can be glued to the existing class. As shown in Code List 5, the implementation of Person class in Person.h only provides the logics required by the domain model. And the implementation of the JSON conversion is put in the JSON category. If JSON conversion is needed, just import Person+JSON.h to get the implementation; otherwise, only import Person.h, the implementation of the JSON conversion is invisible. The category can glue new functionalities without the source code of the glued class -- I often use the category to add new functions into NSString.

Code List 5 - Category
// In Person.h
@interface Person : NSObject

// domain model logic

@end

// In Person+JSON.h
@interface Person (JSON)

+ (instancetype)fromJson:(id)json;

- (void)updateWithJson:(id)json;

- (id)toJson;

@end

// In somewhere alse
#import "Person+JSON.h"

Person* person = [Person fromJson:json];

The fourth feature is extension. This is also a feature of Objective C, and I hope this featureadded into Java to improve the testability. Although the modifiers @public, @protected, and @private are available in Objective C, they are used on member data, not member methods. Objective C does not require that all member methods should be declared in the header file (.h). Therefore, in most case, the methods written in the implementatio file (.m) are considered as the private methods. Sometimes, if private methods can become public methods, to write test case will be more easier. It is good chance to use the extension feature. As an example in Code List 6, public methods are declared in the Person.h, and the methods only public on testing are declared in Person_Private.h. Only the Person.h is public to everyone, and the Person_Private.h is not public. While testing, private methods can be seen by importing the Person_Private.h. (In fact, without additional header files, the extension can be used to open the private methods in test class directly.) Although Java does not separate the header file from the implementation file, providing the private interface implementation may be a similar solution.

Code List 6 - Extension
// In Person.h
@interface Person : NSObject

// public domain model logic

@end

// In Person_Private.h
#import "Person.h"

@interface Person()

- (void)privateMethod;

@end

// In Person.m
#import "Person_Private.h"

@implementation Person

// Implement the methods that declared in Person.h and Person_Private.h

@end

// In PersonTests.m
#import "Person_Private.h"

@implementation PersonTests

- (void)testPrivateMethod {
    // Can see and test -(void)privateMethod method declared in Person_Private.h in test mode.
}

@end

The fifth feature is the preprocessor that can be integrated with IDE. Many developers started to write programs with simple text editors (well, basic funtionalities like syntax highlighted are still offered in these editors), because many IDEs becomes slow and heavy. However, there are still many developers use IDE to write programs -- I ever tried to find an alternative of the slow Eclipse, but I continue to use it because 4.3 improved a lot on performance. The IDEs of Objective C and C# provides many good integration with languages. There are many good IDEs for Java, but Java does not provide features to support IDE. For example, I like to organize methods in a class baed on their functions, and in Objective C, I would like to use #param mark - UITableViewDelegate Methods to collect the methods for UITableViewDelegate together, and in C#, I can use a pair of #region Properties and #endregion to wrap all properties in the same block. And IDE can optimize the UI based on these preprocessors. In XCode, the navigation bar (Figure 1) will classify the methods based on the name marked in #param mark, and this will be easier to find a method.

Figure 1 - XCode provides integration with preprocessors

In recent years, new languages focus on the productivity and improve the readability (abstraction level). And most important is that they can develop the domain specific languages easily. That is not easy for Java. In fact, the features mentioned in the article are something like syntax sugar but they can improve the readability and abstraction level. Therefore, I think these features are useful in Java.

← 希望Java未來能新增的特性 Quick Glance of Java 8 - Default Methods →