• No results found

SDN Community Contribution

N/A
N/A
Protected

Academic year: 2021

Share "SDN Community Contribution"

Copied!
9
0
0

Loading.... (view fulltext now)

Full text

(1)

SDN Community Contribution

(This is not an official SAP document.)

Disclaimer & Liability Notice

This document may discuss sample coding or other information that does not include SAP official interfaces and therefore is not supported by SAP. Changes made based on this information are not supported and can be overwritten during an upgrade.

SAP will not be held liable for any damages caused by using or misusing the information, code or methods suggested in this document, and anyone using these methods does so at his/her own risk.

SAP offers no guarantees and assumes no responsibility or liability of any type with respect to the content of this technical article or code sample, including any liability resulting from incompatibility between the content within this document and the materials and services offered by SAP. You agree that you will not hold, or seek to hold, SAP responsible or liable with respect to the content of this document.

(2)

Applies To:

This article applies to all SAP technology groups that use Java.

Summary

This article describes the new features of Java 1.5 that have been enhanced or added for Ease of Development.

By: Tarun Gugnani

Company: SAP Labs India Pvt. Ltd

Date: 02 Dec 2005

Table of Contents

Applies To:...2

Summary ...2

Table of Contents ...2

Ease of Development Java 1.5 ...2

Generic Types...3

Enhanced For Loop ...3

Autoboxing and Unboxing...4

Typesafe Enums ...5

Varargs ...7

Static Import...7

Annotations (Metadata) ...8

Author Bio...9

Ease of Development Java 1.5

In this article, focus will be on the new features of Java 1.5 that have been added or enhanced for Ease of Development.

Ease of Development was one of the main themes of Java 1.5 development. Many features have been enhanced and added in this area. The features that have been included as a part of Ease of Development are generic types, autoboxing, an enhanced for loop, enumerated types, static import, C-style formatted

input/output, variable arguments, concurrency utilities, and simpler RMI interface generation.

(3)

Generic Types

This is one of the features which Java Community always wanted.

Generics provide a way to create and use type-safe data structures. This means that no longer do you have to create a List of the basic Objects then typecast every time you pull stuff out. One of the major error source at the runtime was wrong type casting while retrieving the object from data structure. Now this problem has been solved & you can declare your list to automatically typecast the stuff inside:

List foodList = createListOfFoodObjects();

for(Iterator i = foodList.iterator() ; i.hasNext() ; ) { Food item = (Food)i.next();

// you have your object now do what you want

// but if we would have used following code we would have got runtime // Error but at compile time it would have compiled fine.

// Junk junk = (Junk)i.next(); }

Now with Generics Runtime problems can be avoided as shown below in the example.

List<Food> foodList = createListOfFoodObjects();

for(Iterator<String> i = foodList.iterator() ; i.hasNext() ; ) { Food item = (Food)i.next();

The Java compiler also protects things from having non-Food objects inside. If you try to put a String or anything else in, you'll get an error. This means that you can create a list with specific types now instead of just objects. These exist in other classes such as Map which uses two arguments to declare. First one is used for key type & the second one is used for value type.

Map<String, Food> foodMap = new HashMap<String, Food>();

This creates a map that uses a String as a key and a Food object as value.

Now the question comes is this totally fool proof & will we catch all the problems at compile time? The answer to this is NO.

There is one catch in this you can always have a String iterator & iterate over Non-String objects which will be caught at runtime & compiler does not catch this.

Also, sometimes when using a type that can be parameterized, but not specifying the parameter type (which you define in angle brackets) you can get lint warnings. This just indicates that you haven't provided a specific type, and the current definition of the type is not clear.

Enhanced For Loop

This is probably one of the coolest new features as a part of Ease of Development. It's not always convenient to use Iterators & most of the programmers do not like it. Well,It’s a good news for all of them now that they there's a way around them now!.

(4)

for(Iterator myIterator = listOfFoodItems.iterator() ; myIterator.hasNext() ; ) {

Object foodItem = myIterator.next(); myUser.eat(foodItem);

}

Now let's see how it can be done in Java 1.5.

for(Object foodItem : listOfFoodItems) { myUser.eat(foodItem);

}

This also works with arrays too.

int[] numbers = { 1, 2, 3, 4, 5, 6 , 7, 8, 9 }; for(int myNum : numbers) {

// Wow I have got my Number with new For Loop System.out.println(myNum);

}

Now lets take a scenario that you want to get your custom class to work with this enhanced for loop. Then following has to be done

1) You have to implement Iterable (or extend something that does). 2) Tell Iterable what type of things you iterate over.

You can define a custom iterator to do something more robust, but for this illustration, I'm just going to take the existing one.

public class FoodBasket implements Iterable<FoodItem> { /** structure for storing the food items */

private ArrayList<FoodItem> foodItems; /**

* Implemented for Iterable. */ public Iterator<FoodItem>() { return foodItems.iterator(); } // Other methods }

Autoboxing and Unboxing

This feature eliminates the drudgery of manual conversion between primitive types and corresponding wrapper types

As any Java programmer knows, you can’t put any primitive type into a collection. As collections can only hold object references, so you always have to box primitive values into the appropriate wrapper class (for Example Integer in the case of int). And whenever you take the object out of the collection, you get the Wrapper object that you put in; if you need a primitive type out of it, you must unbox the wrapper object using the method provided in wrapper class. All of this boxing and unboxing is a pain for programmers. The autoboxing

(5)

Previously all the programmers had to use code similar to the example below.

ArrayList numberList = new ArrayList() int i = 20

// this is not allowed //numberList.add(i);

Integer intObject = new Integer(i); int j = intObject.intValue();

…but now the unnecessary steps has been removed with auto-boxing & auto-unboxing

Integer intObject = 20; int j = intObject;

This is pretty nice. Now you can use ++ and other similar operators with the wrapper types too. Typesafe Enums

This flexible object-oriented enumerated type feature allows you to create enumerated types with arbitrary methods and fields. It provides all the benefits of the Typesafe Enum pattern without the verbosity and the error-proneness

Enums are just magic classes to help prevent the methodless-interface antipattern. They let you make classes that will enumerate values, but also keep the types specific. Before, we could simulate enums with a bunch of static final int variables or something. The problem with those is that you could confuse any

int with one of the constants. As shown in the example.below

public class VCTeam {

public static final int TARUN = 0; public static final int LATHA = 1; public static final int ANSHU = 2; public static final int PRAVEEN = 3; };

The above implementation has severe problems like"

Not typesafe - Since a variable is just an int you can pass in any other int value where a staffcode.is required, or add two staffcodes together which does not make any sense.

No namespace - You must prefix constants of an int enum with a string (in this case VCTeam_) to avoid collisions with other int enum types.

Brittleness - Because int enums are compile-time constants, they are compiled into clients that use them. If a new constant is added between two existing constants or the order is changed, clients must be recompiled. If they are not, they will still run, but their behavior will be undefined.

Printed values are uninformative - Because they are just ints, if you print one out all you get is a number, which tells you nothing about what it represents, or even what type it is.

(6)

public enum VCTeam { TARUN, LATHA, ANSHU, PRAVEEN, }; VCTeam x = VCTeam.TARUN;

Another feature which Enumeration provides is that you don't have to keep track of separate information to store, say the peoples' full names. You can now associate them directly, just like in a class. Each of the values of MyStaff are instances of the MyStaff enumeration, so we can define a constructor and a

toString() method.

public enum VCTeam { TARUN(“Tarun Gugnani”), LATHA(“Latha Nagaraj”), ANSHU(“Anshu Jain”), PRAVEEN(“Praveen Sinha”), private String name;

public VCTeam (String name) { this.name = name; } public String toString() { return this.name; } }

VCTeam x = VCTeam.TARUN; System.out.println(x);

Still we are not done with enumeration. Now you can also give each enumerated value a custom body. Since they're each instances, you could design a toString() method for each separately as shown below in the example

public enum VCTeam {

TARUN("Tarun Gugnani") { public String toString() {

return name + "([email protected])"; }

},

// and so.on for the rest... private String name;

public VCTeam(String name) { this.name = name; } }

VCTeam x = VCTeam.TARUN; System.out.println(x);

(7)

Varargs

This feature eliminates the need for manually boxing up argument lists into an array when invoking methods that accept variable-length argument lists.

Look at the screenshot below

C:/> java ArgumentTest arg1 arg2 arg3 Thanks for providing 3 arguments!! Good Bye !!

...

Well this is how you run your stand alone java program & you don't have to pass an array of arguments. The runtime automatically converts the arguments into an array of strings. You can do that now in all of your methods. As shown below in example:

Earlier we used to do this.

public class VariableArguments {

public static void main(String[] args) {

String[] argumentsToBePassed = {"arg1", "arg2", "arg3"}; someMethod(argumentsToBePassed);

}

public void someMethod(String[] args) {

System.out.println("Thanks for providing " + args.length + " arguments!!"); System.out.println("Good Bye !!");

} }

Now you can declare it more easily, and not have to construct the array ahead of time:

public class VariableArguments {

public static void main(String[] args) { someMethod("a", "b", "c");

}

public void someMethod(String... args) {

System.out.println("Thanks for providing " + args.length + " arguments!!"); System.out.println("Good Bye !!");

} }

Please note that when you use the ... syntax, it automatically treats that parameter as an array but you don't actually have to pass it in that manner.

Static Import

This new feature lets you avoid qualifying static members with class names without the shortcomings of the "Constant Interface antipattern

Whenever you want to access static members, it is always necessary to qualify references with the class they came from. For example,

(8)

As a workaround to this most of the programmers sometimes put static members into an interface and inherit from that interface. This is a not good idea. In fact, it's such a bad idea that there's a name for it: the Constant Interface Antipattern. The problem is that a class's use of the static members of another class is a mere implementation detail. When a class implements an interface, it becomes part of the class's public API. Implementation details should not be leaked into public APIs.

For example:

public interface MyConstants {

public static final float PI = Math.PI; and so on

}

Above class we created just to access few constants directly in my class which requires some static members. This is wrong from the design point of view

The static import construct allows unqualified access to static members without inheriting from the type containing the static members. Instead, the program imports the members, either individually or in mass.

For example:

import static java.lang.Math.PI;// Importing individually import static java.lang.Math.*;// Importing in mass

Annotations (Metadata)

This is the weirdest part of Java 1.5. Annotations are not really something that will affect how you program in Java, unless you need to associate some sort of metadata or annotations with classes, methods, variables, etc.

This language feature lets you avoid writing boilerplate code under many circumstances by enabling tools to generate it from annotations in the source code. This leads to a "declarative" programming style where the programmer says what should be done and tools emit the code to do it. Also it eliminates the need for maintaining "side files" that must be kept up to date with changes in source files. Instead the information can be maintained in the source file.

Lets understand what are annotations. Annotations provide extra information about the classes you write. Annotations can be read using the Reflection package. These are useful because you can attach extra information to your code that may determine how it is used or maybe if it is used at all.

For example, in Java 1.5, you can declare your intent to override a method like toString() in one of your classes:

public class MyClass extends Object { @Override

public String toString() {

return "overridden toString method!"; }

(9)

In the above example, we declare that we will override the immediately following toString() method. So the compiler looks in our superclass (Object) for the same method and makes sure it exists. If for some reason we had overloaded toString() by declaring it with different parameters and maybe return type, then the compiler would throw an error saying we didn't override correctly. This is really useful if you want to make sure you override a method as opposed to simply overloading it.

Of course you can define your own annotations. They're basically like interfaces, but they can contain values.

For example:

public @interface Meeting { String agenda();

String time(); String venue(); }

The above annotation declares three members: agenda, time, venue and sets them up to have "getters" and "setters" automatically! That means each @Meeting annotation has those three fields associated with it, and we don't have to define the getters and setters methods to set them up. If we define above mentioned annotation as shown below, we can use it to mark code that we use for the DesignMeeting:

@Meeting(agenda="design",

time="30th Dec 2005 2p.m ", venue="Meeting Room Number 5") public class MyMeeting {

//... }

And now the @Meeting type of data is associated with my class, ”MyMeeting”. Later on, I could write an analyzer that goes through all of my code and lets me know which classes were used at Meeting as well as which Meetings they were used at and when. This specific example doesn't have any effect on the way

MyMeeting operates.

So the annotations require two-fold cooperation: the programmer must properly annotate his/her code to provide adequate metadata needed and other developers who will want to know this metadata must know how to extract it using the Java Reflection package.

Author Bio

Tarun Gugnani is currently working with Visual composer development team in SAP labs India. He has more than 4 years of experience in java technology.

References

Related documents