Tuesday, April 15, 2014

Programmatic Access to Sizes of Java Primitive Types

One of the first things many developers new to Java learn about is Java's basic primitive data types, their fixed (platform independent) sizes (measured in bits or bytes in terms of two's complement), and their ranges (all numeric types in Java are signed). There are many good online resources that list these characteristics and some of these resources are the Java Tutorial lesson on Primitive Data Types, The Eight Data Types of Java, Java's Primitive Data Types, and Java Basic Data Types.

Java allows one to programmatically access these characteristics of the basic Java primitive data types. Most of the primitive data types' maximum values and minimum values have been available for some time in Java via the corresponding reference types' MAX_VALUE and MIN_VALUE fields. J2SE 5 introduced a SIZE field for most of the types that provides each type's size in bits (two's complement). JDK 8 has now provided most of these classes with a new field called BYTES that presents the type's size in bytes (two's complement).

DataTypeSizes.java
package dustin.examples.jdk8;

import static java.lang.System.out;
import java.lang.reflect.Field;

/**
 * Demonstrate JDK 8's easy programmatic access to size of basic Java datatypes.
 * 
 * @author Dustin
 */
public class DataTypeSizes
{
   /**
    * Print values of certain fields (assumed to be constant) for provided class.
    * The fields that are printed are SIZE, BYTES, MIN_VALUE, and MAX_VALUE.
    * 
    * @param clazz Class which may have static fields SIZE, BYTES, MIN_VALUE,
    *    and/or MAX_VALUE whose values will be written to standard output.
    */
   private static void printDataTypeDetails(final Class clazz)
   {
      out.println("\nDatatype (Class): " + clazz.getCanonicalName() + ":");
      final Field[] fields = clazz.getDeclaredFields();
      for (final Field field : fields)
      {
         final String fieldName = field.getName();
         try  
         {
            switch (fieldName)
            {
               case "SIZE" :  // generally introduced with 1.5 (twos complement)
                  out.println("\tSize (in bits):  " + field.get(null));
                  break;
               case "BYTES" : // generally introduced with 1.8 (twos complement)
                  out.println("\tSize (in bytes): " + field.get(null));
                  break;
               case "MIN_VALUE" :
                  out.println("\tMinimum Value:   " + field.get(null));
                  break;
               case "MAX_VALUE" :
                  out.println("\tMaximum Value:   " + field.get(null));
                  break;
               default :
                  break;
            }
         }
         catch (IllegalAccessException illegalAccess)
         {
            out.println("ERROR: Unable to reflect on field " + fieldName);
         }
      }
   }

   /**
    * Demonstrate JDK 8's ability to easily programmatically access the size of
    * basic Java data types.
    * 
    * @param arguments Command-line arguments: none expected.
    */
   public static void main(final String[] arguments)
   {
      printDataTypeDetails(Byte.class);
      printDataTypeDetails(Short.class);
      printDataTypeDetails(Integer.class);
      printDataTypeDetails(Long.class);
      printDataTypeDetails(Float.class);
      printDataTypeDetails(Double.class);
      printDataTypeDetails(Character.class);
      printDataTypeDetails(Boolean.class);
   }
}

When executed, the code above writes the following results to standard output.

The Output

Datatype (Class): java.lang.Byte:
 Minimum Value:   -128
 Maximum Value:   127
 Size (in bits):  8
 Size (in bytes): 1

Datatype (Class): java.lang.Short:
 Minimum Value:   -32768
 Maximum Value:   32767
 Size (in bits):  16
 Size (in bytes): 2

Datatype (Class): java.lang.Integer:
 Minimum Value:   -2147483648
 Maximum Value:   2147483647
 Size (in bits):  32
 Size (in bytes): 4

Datatype (Class): java.lang.Long:
 Minimum Value:   -9223372036854775808
 Maximum Value:   9223372036854775807
 Size (in bits):  64
 Size (in bytes): 8

Datatype (Class): java.lang.Float:
 Maximum Value:   3.4028235E38
 Minimum Value:   1.4E-45
 Size (in bits):  32
 Size (in bytes): 4

Datatype (Class): java.lang.Double:
 Maximum Value:   1.7976931348623157E308
 Minimum Value:   4.9E-324
 Size (in bits):  64
 Size (in bytes): 8

Datatype (Class): java.lang.Character:
 Minimum Value:   

UPDATE: Note that, as Attila-Mihaly Balazs has pointed out in the comment below, the MIN_VALUE values showed for java.lang.Float and java.lang.Double above are not negative numbers even though these constant values are negative for Byte, Short, Int, and Long. For the floating-point types of Float and Double, the MIN_VALUE constant represents the minimum absolute value that can stored in those types.

Although the characteristics of the Java primitive data types are readily available online, it's nice to be able to programmatically access those details easily when so desired. I like to think about the types' sizes in terms of bytes and JDK 8 now provides the ability to see those sizes directly measured in bytes.

Monday, April 14, 2014

New BigInteger Methods in Java 8

Attention to new features in JDK 8 has rightfully been largely focused on new language features and syntax. However, there are some nice additions to the libraries and APIs and in this post I cover four new methods added to the BigInteger class: longValueExact(), intValueExact(), shortValueExact(), and byteValueExact().

All four of the newly introduced "xxxxxExact()" methods throw an ArithmeticException if the number contained in the BigInteger instance cannot be provided in the specified form (specified in the method's name) without loss of information. BigInteger already had methods intValue() and longValue() as well as inherited (from Number) methods shortValue() and byteValue(). These methods do not throw exceptions if the BigInteger value loses information in the presentation as one of these types. Although at first glance this may seem like an advantage, it means that code that uses the results of these methods uses values that are not accurate without any ability to know that information was lost. The new "xxxxxExact" methods throw an ArithmenticException rather than pretending to provide a result that has lost significant information.

The following simple code listing demonstrates the "legacy" methods that present wrong data in types byte, short, int, and long rather than throwing an exception. The same code also demonstrates use of the new "xxxxxExact" methods that throw an exception when information is lost rather than presenting a bad representation. The output of running this code follows the code and demonstrates how the methods behave differently when the BigInteger contains a value with more information than the returned byte, short, int, or long can represent.

BigIntegerDem.java
package dustin.examples.jdk8;

import static java.lang.System.out;
import java.math.BigInteger;

/**
 * Demonstrate the four new methods of BigInteger introduced with JDK 8.
 * 
 * @author Dustin
 */
public class BigIntegerDemo
{
   /**
    * Demonstrate BigInteger.byteValueExact().
    */
   private static void demonstrateBigIntegerByteValueExact()
   {
      final BigInteger byteMax = new BigInteger(String.valueOf(Byte.MAX_VALUE));
      out.println("Byte Max: " + byteMax.byteValue());
      out.println("Byte Max: " + byteMax.byteValueExact());
      final BigInteger bytePlus = byteMax.add(BigInteger.ONE);
      out.println("Byte Max + 1: " + bytePlus.byteValue());
      out.println("Byte Max + 1: " + bytePlus.byteValueExact());
   }

   /**
    * Demonstrate BigInteger.shortValueExact().
    */
   private static void demonstrateBigIntegerShortValueExact()
   {
      final BigInteger shortMax = new BigInteger(String.valueOf(Short.MAX_VALUE));
      out.println("Short Max: " + shortMax.shortValue());
      out.println("Short Max: " + shortMax.shortValueExact());
      final BigInteger shortPlus = shortMax.add(BigInteger.ONE);
      out.println("Short Max + 1: " + shortPlus.shortValue());
      out.println("Short Max + 1: " + shortPlus.shortValueExact());
   }

   /**
    * Demonstrate BigInteger.intValueExact().
    */
   private static void demonstrateBigIntegerIntValueExact()
   {
      final BigInteger intMax = new BigInteger(String.valueOf(Integer.MAX_VALUE));
      out.println("Int Max: " + intMax.intValue());
      out.println("Int Max: " + intMax.intValueExact());
      final BigInteger intPlus = intMax.add(BigInteger.ONE);
      out.println("Int Max + 1: " + intPlus.intValue());
      out.println("Int Max + 1: " + intPlus.intValueExact());
   }

   /**
    * Demonstrate BigInteger.longValueExact().
    */
   private static void demonstrateBigIntegerLongValueExact()
   {
      final BigInteger longMax = new BigInteger(String.valueOf(Long.MAX_VALUE));
      out.println("Long Max: " + longMax.longValue());
      out.println("Long Max: " + longMax.longValueExact());
      final BigInteger longPlus = longMax.add(BigInteger.ONE);
      out.println("Long Max + 1: " + longPlus.longValue());
      out.println("Long Max + 1: " + longPlus.longValueExact());
   }

   /**
    * Demonstrate BigInteger's four new methods added with JDK 8.
    * 
    * @param arguments Command line arguments.
    */
   public static void main(final String[] arguments)
   {
      System.setErr(out); // exception stack traces to go to standard output
      try
      {
         demonstrateBigIntegerByteValueExact();
      }
      catch (Exception exception)
      {
         exception.printStackTrace();
      }

      try
      {
         demonstrateBigIntegerShortValueExact();
      }
      catch (Exception exception)
      {
         exception.printStackTrace();
      }

      try
      {
         demonstrateBigIntegerIntValueExact();
      }
      catch (Exception exception)
      {
         exception.printStackTrace();
      }

      try
      {
         demonstrateBigIntegerLongValueExact();
      }
      catch (Exception exception)
      {
         exception.printStackTrace();
      }
   }
}
The Output
Byte Max: 127
Byte Max: 127
Byte Max + 1: -128
java.lang.ArithmeticException: BigInteger out of byte range
 at java.math.BigInteger.byteValueExact(BigInteger.java:4428)
 at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerByteValueExact(BigIntegerDemo.java:23)
 at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java:75)
Short Max: 32767
Short Max: 32767
Short Max + 1: -32768
java.lang.ArithmeticException: BigInteger out of short range
 at java.math.BigInteger.shortValueExact(BigInteger.java:4407)
 at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerShortValueExact(BigIntegerDemo.java:36)
 at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java:84)
Int Max: 2147483647
Int Max: 2147483647
Int Max + 1: -2147483648
java.lang.ArithmeticException: BigInteger out of int range
 at java.math.BigInteger.intValueExact(BigInteger.java:4386)
 at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerIntValueExact(BigIntegerDemo.java:49)
 at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java:93)
Long Max: 9223372036854775807
Long Max: 9223372036854775807
Long Max + 1: -9223372036854775808
java.lang.ArithmeticException: BigInteger out of long range
 at java.math.BigInteger.longValueExact(BigInteger.java:4367)
 at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerLongValueExact(BigIntegerDemo.java:62)
 at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java:102)

As the above output demonstrates, the new BigInteger methods with "xxxxxExact" in their name will not present inaccurate representations when the returned type cannot hold the information in BigInteger instance. Although exceptions are generally not one of our favorite things, they are almost always going to be better than getting and using wrong data and not even realizing it is wrong.

Wednesday, April 9, 2014

Dubious Aspects of Features of JDK 8

Most of us who develop with Java are generally enthusiastic for the features and improvements that come with JDK 8. However, there have been several recent posts that have pointed out some features that can be misused and abused and might lead to some additional issues in the future. These features, which remind me of the introduction of autoboxing in J2SE 5, have their useful situations, but can also lead to issues when not correctly understood and applied. In this post, I use references to other peoples' posts written about these dubious features. Note that this post is not about the "normal" known issues that are associated with any release.

Lambda expressions seem to be the biggest new feature of JDK 8, but Tal Weiss has written a post called The Dark Side Of Lambda Expressions in Java 8. In that post, Weiss writes about a "dark side" to lambda expressions and the Nashorn JavaScript engine (which he argues is the second biggest feature of JDK 8). He talks about the "distance between your code and the runtime" and points out that "we’re paying the price for shorter, more concise code with more complex debugging, and longer synthetic call stacks."

In Love and hate for Java 8, Andrew C. Oliver and Michael Brush provide a nice introduction to some of the main new features of JDK 8. They are argue that default methods on interfaces "allow a form of multiple inheritance" and will "probably [be] the detail that will concern most people in Java 8." He concludes the article with the assessment, "The feature that is going to be dangerous is functional interfaces. If they are not used properly, they could cause a lot of headaches."

Peter Verhas has written a detailed analysis of the potential issues with default methods on interfaces in the posts Java 8 default methods: what can and can not do? and How not to use Java 8 default methods. In one post, he states, "Adding a default method to an interface may render some class unusable." In the other post, he adds, "The default method is a technological mistake" and references the fact that default methods were added to Java interfaces to support backward compatibility of existing implementations with methods that need to be added to interfaces to support new JDK 8 features.

Lukas Eder's The Dark Side of Java 8 post expresses different concerns about default methods: the inability to make a default method final or synchronized and introduction of the "default" keyword. Another interesting "caveat" pointed out in this post is the effect lambda expressions have on overloading.

Another Tal Weiss post, New Parallelism APIs in Java 8: Behind The Glitz and Glamour, looks at some issues Weiss observed when measuring performance of the "new Java 8 parallel operation APIs" under load. Weiss observes, "adding threads in what already is a multi-threaded environment doesn’t help you" and reminds us, "While these are very strong and easy-to-use APIs, they’re not a silver bullet. We still need to apply judgment as to when to employ them."

Lukas Krecan warns Think twice before using Java 8 parallel streams and writes, "The problem is that all parallel streams use common fork-join thread pool and if you submit a long-running task, you effectively block all threads in the pool." To deal with this, Krecan advises either "[ensuring] that all tasks submitted to the common fork-join pool will not get stuck and will finish in a reasonable time" or "not use parallel streams and wait until Oracle allows us to specify the thread pool to be used for parallel streams."

Edwin Dalorzo's post Why There’s Interface Pollution in Java 8 looks at how type erasure, checked exceptions, and lack of value types (JEP 169) led to design decisions in JDK 8 that have "polluted" Java interfaces. The post mixes quotes from Brian Goetz regarding JDK 8 design decisions with the author's own commentary to make the point that "there are good explanations for the dark side to exist."

There are, of course, issues between newly released JDK 8 and tools built on Java. For example, in the post Hello Java 8 (and how it makes GlassFish speechless...), Cay Horstmann documents GlassFish 4 not writing any stack trace whatsoever when he had "[compiled] the WAR with the wrong version of Java."

Although the referenced posts point out legitimate issues of concern related to some of JDK 8's most anticipated features such as lambda expressions, streams, interface default methods, and the Nashorn JavaScript engine, I am still excited about the brave new world of Java development with JDK 8. The posts highlighted in this post are reminders to use these new features carefully and judiciously so that we enjoy the advantages they bring while mitigating as much as possible the new dangers and costs they present when used less wisely.

Tuesday, April 8, 2014

Responses to Contributions of Individual Programming Languages to Software Development

My recent post Contributions of Individual Programming Languages to Software Development has received numerous useful and informative responses that I highlight here. Because select posts to this blog are syndicated to JavaWorld, DZone/JavaLobby, and Java Code Geeks, the responses to my blog posts sometimes appear on those various sites (all of which, by the way, are highly useful sites for Java developers). I am using this post as a centralized location for these educational responses.

When I originally published Contributions of Individual Programming Languages to Software Development, I forgot to include my text on Java, other JVM languages, PHP, and Ada, but those are now covered in the original post and are reflected as well in the DZone and Java Code Geeks syndicated versions.

Clay Shannon highlighted (and Hans Salvisberg emphasized) the influence of Delphi on software development in a comment on the DZone syndicated version of my post. Clay wrote that C# "really drew most of its inspiration from Delphi; Anders Hejlsberg, the C# architect, was poached/seduced away from Borland by the Redmondians. Hejlsberg was the main cat behind Delphi, and forsooth, many Delphiesque thingamajigs reappeared rebranded in his other brainchild, C#."

Luciano Quadraccia wrote on the DZone version of my post about ALGOL and provided a historical anecdote to back up the premise of the significant influence of that language. He concluded, "So, ALGOL was the preferred vehicle for code sharing (at least in the scientific community), and was probably the first general purpose mainstream language with recursion."

In a response to the Java Code Geeks version of my post, Howard Fear mentioned the influences of languages such as Tcl ("really took the concept of DSLs to another level") and Eiffel (one I wish I had mentioned in my original post because I agree with Howard's assessment that it "had a big impact on the development of object oriented programming languages").

There were a few programming languages mentioned that I knew nothing or next to nothing about. These include Forth (mentioned on DZone by Curtis Esac). Howard Fear also mentioned Snobol in a response to the Java Code Geeks version of my post and stated that without Snobol "there would be no shell, awk, perl, or the myriad of other scripting languages."

In a response to my original post, Boffin wrote of the influence of frameworks/computing platforms CUDA and Hadoop.

Monday, April 7, 2014

Constructor/Method Parameters Metadata Available Via Reflection in JDK 8

One of the lesser advertised new features of JDK 8 is the optional ability to include parameter metadata in compiled Java classes [JDK Enhancement Proposal (JEP) 118]. This feature allows Java applications to access this parameter metadata information at runtime via reflection.

The Java Tutorials' Reflection API trail includes a lesson called Obtaining Names of Method Parameters that discusses and demonstrates how to apply this new feature in Java 8. The lesson includes an example Java class MethodParameterSpy that can be run against a provided Java class to indicate characteristics of method and constructor parameters. This lesson also emphasizes that this is an optional feature because storing additional parameter metadata in .class files increases the size of those files. The lesson also points out that there may be some cases where parameter names have sensitive information that the developer does not want available in the compiled .class files.

The additional parameter metadata can be included in .class files compiled in Java 8 by passing the -parameters option to the javac compiler. This -parameters option is also shown when one types javac -help as shown in the next screen snapshot.

The Oracle TechNotes page on javac indicates how this additional method/constructor parameter data can be accessed at runtime: "Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them." The following code snippet (class called ParameterDisplayer) demonstrates this (emphasis is on the displayParametersMetadata(String[]) method).

ParameterDisplayer.java
package dustin.examples.jdk8;

import static java.lang.System.out;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;

/**
 * Uses JDK 8 Parameter class to demonstrate metadata related to the parameters
 * of the methods and constructors of the provided class (includes private,
 * protected, and public methods, but does not include methods inherited from
 * parent classes; those classes should be individually submitted).
 * 
 * @author Dustin
 */
public class ParameterDisplayer
{
   private static void displayParametersMetadata(final String[] classesNames)
   {
      for (final String className : classesNames)
      {
         try
         {
            final Class clazz = Class.forName(className);

            // Get all class's declared methods (does not get inherited methods)
            final Method[] declaredMethods = clazz.getDeclaredMethods();
            for (final Method method : declaredMethods)
            {
               writeHeader(
                    "Method " + method.toGenericString()
                  + " has " + method.getParameterCount() + " Parameters:");
               int parameterCount = 0;
               final Parameter[] parameters = method.getParameters();
               for (final Parameter parameter : parameters)
               {
                  out.println(
                       "\targ" + parameterCount++ + ": "
                     + (parameter.isNamePresent() ? parameter.getName() : "Parameter Name not provided,")
                     + (isParameterFinal(parameter) ? " IS " : " is NOT ")
                     + "final, type " + parameter.getType().getCanonicalName()
                     + ", and parameterized type of " + parameter.getParameterizedType()
                     + " and " + (parameter.isVarArgs() ? "IS " : "is NOT ")
                     + "variable." );
               }
            }
         }
         catch (ClassNotFoundException cnfEx)
         {
            out.println("Unable to find class " + className);
         }
      }
   }

   private static void writeHeader(final String headerText)
   {
      out.println("\n==========================================================");
      out.println("= " + headerText);
      out.println("==========================================================");
   }

   /**
    * Indicate whether provided Parameter is final.
    * 
    * @param parameter Parameter to be tested for 'final' modifier.
    * @return {@code true} if provided Parameter is 'final'.
    */
   private static boolean isParameterFinal(final Parameter parameter)
   {
      return Modifier.isFinal(parameter.getModifiers());
   }

   public static void main(final String[] arguments)
   {
      if (arguments.length < 1)
      {
         out.println("You must provide the fully qualified name of at least one class.");
         System.exit(-1);
      }

      displayParametersMetadata(arguments);
   }
}

I had initially thought about running this class against a well-known class of the JDK, but realized that would not be too helpful because those classes are not likely to have been built with the -parameters option. Therefore, I have created a simple example class to aid with the demonstration. It is called ManyMethods and is shown next.

ManyMethods.java
package dustin.examples.jdk8;

import java.util.List;

/**
 * Class with numerous methods intended to be used in demonstrating JDK 8's new
 * Parameter class.
 * 
 * @author Dustin
 */
public class ManyMethods
{
   public ManyMethods() {}

   private void addArrayOfStrings(String[] strings) {}

   private void addManyStrings(final String ... strings) {}

   private void addListOfStrings(final List<String> strings) {}

   @Override
   public String toString()
   {
      return "ManyMethods";
   }
}

The next two screen snapshots demonstrate running ParameterDisplayer against instances of ManyMethods compiled without and with the -parameters option. The most notable differences are that the parameter names are not provided when compiled without the -parameters option. Also, there is no trusted information on whether the parameter is final when compiled without the -parameters option. The Parameter.getModifiers() method does not include final when compiled without -parameters whether or not the parameter is actually final.

The ParameterDisplayer class uses Parameter.isNamePresent() to programmatically identify that the parameter name is not present (when not compiled with the -parameters option). Had that check not been made, the parameter name returned by Parameter.getName() would have been "arg" plus the number of the parameter (arg0 for the first parameter, arg1 for the second parameter, and so on).

Two of the three methods in ManyMethods class that had a parameter had the final modifier on that parameter. These cases were correctly identified by reflection using Parameter.getModifiers() only when the class was compiled with the -parameters option.

Slightly Related Side Note: Sun/Oracle tools documentation has always consisted of a "windows" page and a "solaris" page, with the latter typically being used to describe how the particular tool works on all flavors on Linux and Unix. I noted that this has changed with the Java 8 documentation. This documentation still has a "windows" version, but the Unix/Linux version now has "unix" in its URL. To illustrate this, here are the URLs for Java SE 7 and Java SE 8 javac tool pages:

Returning to the new (with Java 8) Parameter class, it's worth noting that there is an increase in compiled .class files that store this additional parameter metadata. For my ManyMethods class shown above, the .class file was enlarged from 909 bytes to 961 bytes.

Constructor, like Method, extends Executable, and so the Constructor class enjoys the same getParameters method as Method. Java 8 provides more detail on method and constructor parameters when the code is explicitly compiled with that extra information.

Tuesday, April 1, 2014

Compiling and Running Java Without an IDE

A recent Java subreddit thread called "Compiling Java Packages without IDE" posed the question, "is [there] a command that compiles a group of java files that are inside a package into a separate folder (let's just call it bin), and how would I go about running the new class files?" The post's author, kylolink, explains that "When I started out using Java I relied on Eclipse to do all the compiling for me and just worried about writing code." I have seen this issue many times and, in fact, it's what prompted my (now 4 years old) blog post GPS Systems and IDEs: Helpful or Harmful? I love the powerful modern Java IDEs and they make my life easier on a daily basis, but there are advantages to knowing how to build and run simple Java examples without them. This post focuses on how to do just that.

In my blog post Learning Java via Simple Tests, I wrote about how I sometimes like to use a simple text editor and command-line tools to write, build, and run simple applications. I have a pretty good idea now how my much "overhead" my favorite Java IDEs require and make an early decision whether the benefits achieved from using the IDE are sufficient to warrant the "overhead." In most real applications, there's no question the IDE "overhead" is well worth it. However, for the simplest of example applications, this is not always the case. The rest of this post shows how to build and run Java code without an IDE for these situations.

The Java Code to be Built and Executed

To make this post's discussion more concrete, I will use some very simple Java classes that are related to each other via composition or inheritance and are in the same named package (not in the unnamed package) called dustin.examples. Two of the classes do not have main functions and the third class, Main.java does have a main function to allow demonstration of running the class without an IDE. The code listings for the three classes are shown next.

Parent.java
package dustin.examples;

public class Parent
{
   @Override
   public String toString()
   {
      return "I'm the Parent.";
   }
}
Child.java
package dustin.examples;

public class Child extends Parent
{
   @Override
   public String toString()
   {
      return "I'm the Child.";
   }
}
Main.java
package dustin.examples;

import static java.lang.System.out;

public class Main
{
   private final Parent parent = new Parent();
   private final Child child = new Child();

   public static void main(final String[] arguments)
   {
      final Main instance = new Main();
      out.println(instance.parent);
      out.println(instance.child);
   }
}

The next screen snapshot shows the directory structure with these class .java source files in place. The screen snapshot shows that the source files are in a directory hierarchy representing the package name (dustin/examples because of package dustin.examples) and that this package-reflecting directory hierarchy is under a subdirectory called src. I have also created classes subdirectory (which is currently empty) to place the compiled .class files because javac will not create that directory when it doesn't exist.

Building with javac and Running with java

No matter which approach one uses to build Java code (Ant, Maven, Gradle, or IDE) normally, I believe it is prudent to at least understand how to build Java code with javac. The Oracle/Sun-provided javac command-line tool's standard options can be seen by running javac -help and additional extension options can be viewed by running javac -help -X. More details on how to apply these options can be found in the tools documentation for javac for Windows or Unix/Linux.

As the javac documentation states, the -sourcepath option can be use to express the directory in which the source files exist. In my directory structure shown in the screen snapshot above, this would mean that, assuming I'm running the javac command from the C:\java\examples\javacAndJava\ directory, I'd need to have something like this in my command: javac -sourcepath src src\dustin\examples\*.java. The next screen snapshot shows the results of this.

Because we did not specify a destination directory for the .class files, they were placed by default in the same directory as the source .java files from which they were compiled. We can use the -d option to rectify this situation. Our command could be run now, for example, as javac -sourcepath src -d classes src\dustin\examples\*.java. As stated earlier, the specified destination directory (classes) must already exist. When it does, the command will place the .class files in the designated directory as shown in the next screen snapshot.

With the Java source files compiled into the appropriate .class files in the specified directory, we can now run the application using the Java application launcher command line tool java. This is simply done by following the instructions shown by java -help or by the java tools page and specifying the location of the .class files with the -classpath (or -cp) option. Using both approaches to specify that the classes directory is where to look for the .class files is demonstrated in the next screen snapshot. The last argument is the fully qualified (entire Java package) name of the class who has a main function to be executed. The commands demonstrated in the next screen snapshot is java -cp classes dustin.examples.Main and java -classpath classes dustin.examples.Main.

Building and Running with Ant

For the simplest Java applications, it is pretty straightforward to use javac and java to build and execute the application respectively as just demonstrated. As the applications get a bit more involved (such as code existing in more than one package/directory or more complex classpath dependencies on third-party libraries and frameworks), this approach can become unwieldy. Apache Ant is the oldest of the "big three" of Java build tools and has been used in thousands of applications and deployments. As I discussed in a previous blog post, a very basic Ant build file is easy to create, especially if one starts with a template like I outlined in that post.

The next code listing is for an Ant build.xml file that can be use to compile the .java files into .class files and then run the dustin.examples.Main class just like was done above with javac and java.

build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="BuildingSansIDE" default="run" basedir=".">
   <description>Building Simple Java Applications Without An IDE</description>

   <target name="compile"
           description="Compile the Java code.">
      <javac srcdir="src"
             destdir="classes"
             debug="true"
      includeantruntime="false" />
   </target>

   <target name="run" depends="compile"
           description="Run the Java application.">
      <java classname="dustin.examples.Main" fork="true">
         <classpath>
           <pathelement path="classes"/>
         </classpath>
      </java>
   </target>
</project>

I have not used Ant properties and not included common targets I typically include (such as "clean" and "javadoc") to keep this example as simple as possible and to keep it close to the previous example using javac and java. Note also that I've included "debug" set to "true" for the javac Ant task because it's not true in Ant's default but is true with javac's default. Not surprisingly, Ant's javac task and java task closely resemble the command tools javac and java.

Because I used the default name Ant expects for a build file when it's not explicitly specified (build.xml) and because I provided the "run" target as the "default" for that build file and because I included "compile" as a dependency to run the "run" target and because Ant was on my environment's path, all I need to do on the command line to get Ant to compile and run the example is type "ant" in the directory with the build.xml file. This is demonstrated in the next screen snapshot.

Although I demonstrated compiling AND running the simple Java application with Ant, I typically only compile with Ant and run with java (or a script that invokes java if the classpath is heinous).

Building and Running with Maven

Although Ant was the first mainstream Java build tool, Apache Maven eventually gained its own prominence thanks in large part to its adoption of configuration by convention and support for common repositories of libraries. Maven is easiest to use when the code and generated objects conform to its standard directory layout. Unfortunately, my example doesn't follow this directory structure, but Maven does allow us to override the expected default directory structure. The next code listing is for a Maven POM file that overrides the source and target directories and provides other minimally required elements for a Maven build using Maven 3.2.1.

pom.xml
<project>
   <modelVersion>4.0.0</modelVersion>
   <groupId>dustin.examples</groupId>
   <artifactId>CompilingAndRunningWithoutIDE</artifactId>
   <version>1</version>
  
   <build>
      <defaultGoal>compile</defaultGoal>
      <sourceDirectory>src</sourceDirectory>
      <outputDirectory>classes</outputDirectory>
      <finalName>${project.artifactId}-${project.version}</finalName>
   </build>
</project>

Because the above pom.xml file specifies a "defaultGoal" of "compile" and because pom.xml is the default custom POM file that the Maven executable (mvn) looks for and because the Maven installation's bin directory is on my path, I only needed to run "mvn" to compile the .class files as indicated in the next screen snapshot.

I can also run the compiled application with Maven using the command mvn exec:java -Dexec.mainClass=dustin.examples.Main, which is demonstrated in the next screen snapshot.

As is the case with Ant, I would typically not use Maven to run my simple Java application, but would instead use java on the compiled code (or use a script that invokes java directly for long classpaths).

Building and Running with Gradle

Gradle is the youngest, trendiest, and hippest of the three major Java build tools. I am sometimes skeptical of the substance of something that is trendy, but I have found many things to like about Gradle (written in Groovy instead of XML, built-in Ant support, built-in Ivy support, configuration by convention that is easily overridden, Maven repository support, etc.). The next example shows a Gradle build file that can be used to compile and run the simple application that is the primary example code for this post. It is adapted from the example I presented in the blog post Simple Gradle Java Plugin Customization.

build.gradle
apply plugin: 'java'
apply plugin: 'application'

// Redefine where Gradle should expect Java source files (*.java)
sourceSets {
    main {
        java {
            srcDirs 'src'
        }
    }
}

// Redefine where .class files are written
sourceSets.main.output.classesDir = file("classes")

// Specify main class to be executed
mainClassName = "dustin.examples.Main"

defaultTasks 'compileJava', 'run'

The first two lines of the build.gradle file specify application of the Java plugin and the Application plugin, bringing a bunch of functionality automatically to this build. The definition of "sourceSets" and "sourceSets.main.output.classesDir" allows overriding of Gradle's Java plugin's default directories for Java source code and compiled binary classes respectively. The "mainClassName" allows explicit specification of which class should be run as part of the Application plugin. The "defaultTasks" line specifies the tasks to be run by simply typing "gradle" at the command line: 'compileJava' is a standard task provided by the Java plugin and 'run' is a standard task provided by the Application plugin. Because I named the build file build.gradle and because I specified the default tasks of 'compileJava' and 'run' and because I have the Gradle installation bin directory on my path, all I needed to do to build and run the examples was to type "gradle" and this is demonstrated in the next screen snapshot.

Even the biggest skeptic has to admit that Gradle build is pretty slick for this simple example. It combines brevity from relying on certain conventions and assumptions with a very easy mechanism for overriding select defaults as needed. The fact that it's in Groovy rather than XML is also very appealing!

As is the case with Ant and Maven, I tend to only build with these tools and typically run the compiled .class files directly with java or a script that invokes java. By the way, I typically also archive these .class into a JAR for running, but that's outside the scope of this post.

Conclusion

An IDE is often not necessary for building simple applications and examples and can even be more overhead than it's worth for the simplest examples. In such a case, it's fairly easy to apply javac and java directly to build and run the examples. As the examples become more involved, a build tool such as Ant, Maven, or Gradle becomes more appealing. The fact that many IDEs support these build tools means that a developer could transition to the IDE using the build tool created earlier in the process if it was determined that IDE support was needed as the simple application grew into a full-fledged project.

Monday, March 31, 2014

Contributions of Individual Programming Languages to Software Development

I've grown weary of the blog posts and forum rants stating why one programming language is better than another. I don't mind when languages are compared to help see how they are different or even when one language is argued as better for a very specific situation for a specific reason. I have yet to find (and never expect to find) a programming language that is better than all other languages for all situations (and this includes HTML5). In fact, I have found the contrary to be true: although I definitely have my favorite handful of programming languages, I recognize that a much wider spectrum of programming languages (even some that I don't personally like) have helped software development as a practice arrive where we are today.

In this blog post, I look at the contributions of several different programming languages to our discipline. In most cases, the listed language was not the very first to introduce the concept or feature, but was the first to make it popular or "mainstream." The purpose of this post is NOT to state which programming language is best or why one is the best thing since sliced bread while another is the worse thing to ever happen to a software developer. I also don't cover markup "languages" such as XML or HTML in this post, though they obviously have had significant influence on software development.

Basic

Most software developers I know have written some code in some form of BASIC (Beginner's All Purpose Symbolic Instruction Code). I remember, long before public availability of the Internet or even mice on PCs, typing in Basic code from magazines I received in the mail with code listings for various simple games and PC utilities. Like many developers, Basic was the language that attracted my interest at a relatively young age to programming. It was from my Basic programming that I learned firsthand the dangers of the goto.

C

C may be the most influential of all programming languages on today's software development. In Steve Yegge's well-known blog post The Next Big Language, Yegge's #1 rule for the next big programming language is that it has "C-like syntax." Many people's favorite programming languages are themselves (interpreter or runtime environment) written in C and many of these languages provide mechanisms (JNI and XS are two examples) for "escaping" to C for performance gains. C also remains one of the most popular and highly used programming languages in the world despite its relatively old age. Wikipedia even has an entry devoted to C-based programming languages.

COBOL

Although COBOL is not a language you read much about in blogs or articles these days, there is a huge amount of deployed code written in COBOL (Common Business-Oriented Language). In Cobol doesn't belong in a museum, Ken Powell writes:

I believe that the spirit of Smithsonian’s Cobol debut is not an indication of its antiquity, but rather a testament to its past, as well as its continued success. Just as Edison’s light bulb was a game-changing invention in its day, Cobol has changed the face of computing, and continues to have a tremendous impact on our everyday lives.

John Breeden II also writes of Cobol's impact on software development in A toast to Cobol, a true computing hero, stating, "Without Cobol, each early computer might have developed its own proprietary computing language. Instead, we started on a path to interoperability that would come in very handy later on."

C#

C#'s status as flagship language of Microsoft's .NET has made it influential out of the box. C#'s syntax and early features also paid homage to and provided evidence of the influence of C, C++, and Java. Although C# borrowed heavily from those languages in its early versions, it also brought its own advancements that were emulated by other languages (in particular by Java). It was Microsoft's plan for migrating legacy Visual Basic applications to the .NET framework (and making use of C# libraries) that demonstrated on a large scale the advantages that the JVM already offered but were rarely used. The multiple language paradigm on the JVM has become huge in recent years, but Microsoft's use of the CLR seemed to be the first to bring this idea to mainstream awareness even though the JVM existed before the CLR.

C++

C++ was the object-oriented language for a while, is still heavily used, and has inspired other highly popular object-oriented languages such as C# and Java. C++ has dominated the "system programming" market and changed how many of us think about programming from completely procedural to object-oriented thinking. C++'s direct influence as a popular language in its own right and indirect influence via "child" languages that have reached their own popularity heights are proof of this language's dramatic influence on software development.

Fortran

The IBM article Fortran: The Pioneering Programming Language states that Fortran (FORMula TRANslator) "became the first computer language standard, 'helped open the door to modern computing,' and may well be the most influential software product in history." This is an interesting read that I highly recommend for learning more about Fortran's impact and influence on software development. Fortran has also been called "the first successful high level programming language."

Haskell

Along with Lisp, one of the first programming languages many of us think of when discussing functional programming is Haskell. As languages such as Scala, Clojure, and even Java 8 bring functional programming concepts to the JVM, it's not difficult to see the roots of these features in languages such as Haskell and Lisp. The Why Haskell matters Wiki page states, "Haskell is a modern general purpose language developed to incorporate the collective wisdom of the functional programming community into one elegant, powerful and general language." There's even a free online book called Learn You a Haskell for Great Good!

JavaScript

JavaScript is one of the most frequently used programming languages today with its strength being web development and mobile development. The HTML5 movement has been influenced by and expanded the influence of JavaScript. There have been numerous tools built to convert other languages to JavaScript and new frameworks and libraries have also been created to ease JavaScript's difficulties (cross-browser incompatibility being a major one). However, most developers developing for web or mobile devices still need basic understanding of JavaScript. JavaScript has also made in-roads on the server side as evidenced by Node.js and by Oracle's choice of JavaScript as the language to use to prove the JVM's applicability to a language significantly different than Java (via Project Nashorn). Finally, JavaScript's influence is seen in other ECMAScript implementations such as ActionScript.

JavaScript provides a good example of a language that has helped shape my thinking when developing in other languages. In the most painful years of Java development before the advent of jQuery and other decent JavaScript libraries and frameworks, those of us working with JavaScript had to use it directly. It wasn't so much JavaScript's idiosyncrasies and corners as it was that the different browsers' DOM implementations' idiosyncrasies and corners that drove the JavaScript developer to anger and frustration. Too much JavaScript code was filled with boilerplate code trying to detect the browser version ("browser sniffing") to act differently depending on the browser. This was problematic because different versions of the same browser might start or stop supporting certain DOM features and it meant constant updating of the browser checks. The realization that it was better to use DOM object detection was huge. The higher level idea is that the code should ask if a certain feature is available and then use it if it is. Today, even in other languages, I think this should be a guiding principle: don't programmatically ask one question that indirectly points to the correct behavior. Instead, when possible, ask the question that directly points to the correct action to take. It may not be as important in other languages as it is in JavaScript, but it's still a useful tactic for code that almost maintains itself.

Lisp

David Chisnall calls Lisp "arguably the most influential programming language of all time" in his post Influential Programming Languages, Part 4: Lisp. Reasons he cites to justify this claim include Lisp being "the very first programming language to provide automatic garbage collection," Lisp's introducing "the idea of the read-evaluate-print loop (REPL)," Lisp's early use of closures/lambdas, and Lisp's "inspiration for pure functional languages" and "inspiration for a number of object-oriented languages." In Why Lisp?, Peter Seibel states, "So, on one hand, Lisp is one of computer science's "classical" languages, based on ideas that have stood the test of time. On the other, it's a thoroughly modern, general-purpose language whose design reflects a deeply pragmatic approach to solving real problems as efficiently and robustly as possible."

Pascal

Like Basic, Pascal is influential on software development because of its wide use as a "learning language." Aspects of Pascal are also seen in other languages. For example, the Oracle database procedural programming language PL/SQL has always felt eerily similar to Pascal. One might argue that Pascal's influence is felt more today indirectly via languages such as PL/SQL than via direct use. On a personal note, Pascal is the first language that I used in more than hobbyist fashion (that was Basic's role for me) as I had high school and college courses that used Pascal and I wrote my first "commercial" application (a sports trading card inventory control system) in Pascal. I still think Pascal offers numerous advantages as a "learning language."

Perl

Perl has been a significant contributor in a wide variety of contexts, especially in early web development (CGI scripts) and in Unix/Linux scripting and development. Perl was often the first taste of a dynamic language for C-style language developers. It also helped many developers to realize the advantage of writing scripts in a language that could be used in all shells rather than using shell-specific scripts. Furthermore, it can be argued that Perl, perhaps more than any other language, has brought the power of regular expressions to the forefront of software development along with some powerful and concise features of sed and awk.

Python

I have no evidence to back this, but it feels to me like Python is the language taking most developers away from using Perl for scripting. There are still countless scripts written in Perl and still be written in Perl, but Python seems to be gaining on the percentage of new scripts being written. There are Python libraries for all types of different domains. For example, in my post Significant Software Development Developments of 2013, I wrote about Python and Big Data. Python seems to appeal to a wide variety of developers in the Java, .NET, C/C++, and other development communities where Python is not the predominant language.

Ruby / Ruby on Rails

Although Ruby on Rails is a framework rather than a language, it is Ruby on Rails that seems to have made Ruby famous outside of Japan and so it's difficult to talk about Ruby's influence without considering Ruby on Rails's influence. Ruby has popularized many object-oriented concepts that were available in other languages that never reached Ruby's level of adoption. Ruby's treatment of everything as an object (no primitives) and its powerful use of dynamic mechanisms in conjunction with object-oriented principles made combined object-oriented structure with a dynamic language in ways that Perl's bolted-on object-orientation could not achieve. Ruby on Rails popularized the concept of configuration by exception that is prevalent today, but was lesser known (Maven, Hibernate, and JavaBeans for example) before Ruby on Rails and the specific and catchy nomenclature of "convention over configuration."

Smalltalk

If we were to measure programming languages by the ratio of influence on other languages and frameworks to existing code base written in that language, Smalltalk might have the highest ratio of them all (though ALGOL would give it a run for its money in terms of code still deployed today). For its relatively small deployed code base, Smalltalk has had tremendous influence of frameworks and much more widely used programming languages (including Java and other object-oriented languages). Smalltalk has influenced other languages' syntax and concepts (such as everything is an object) and has had obvious influence of today's IDEs.

Visual Basic

I won't talk much about Visual Basic here because I've already touched on it at least tangentially in the Basic and C# coverage, but it has been one of the world's most popular programming languages at one time and influenced many developers who got their hobbyist and professional starts with that language. It has also influenced software development through early IDE innovations that provided a glimpse of what Java and other programming language IDEs could (and would) become.


The languages described in this section are descriptions I have added since the post was originally published.

Java

Nicolas Frankel's (@nicolas_frankel and current DZone Dev of the Week) Tweet reminded me I had forgotten to include Java on my list (despite Java having the most personal influence on me of all the programming languages). I rectify that here with the paragraphs I intended to include in the original post.

Given Java's ubiquity in academic and professional programming environments, numerous developers have written Java at one time or another and the sheer number of developers exposed to Java conveys its impact on software development in general. Many new language designers still compare and contrast their languages to Java.

Perhaps Java's biggest influence on programming was its introduction of the JVM and the many benefits associated with a virtual machine. The JVM allowed for better support than most languages had been able to provide for the "write once run anywhere" paradigm. Not only did this increase the ease of portability of Java applications, but it helped many of us start to think that maybe it is best to have data types have the same memory size regardless of the platform for which the application is written. Java's garbage collection mechanism was an almost-too-good-to-be-true feature for those of us who had primarily been using languages that required developers to carefully manage their own memory deallocation. The ability to manipulate Java byte code after compilation has led to numerous JVM-based dynamic languages and was one of the reasons that aspect-oriented programming was arguably best implemented in Java-based products such as AspectJ and the Spring Framework.

One of the first things that impressed me about Java was the Javadoc mechanism. I loved being able to include in-source comments that were generated into documentation viewable in a web browser. As internet use grew, the availability of the standard JDK API, Java EE API, and libraries' and frameworks' APIs online was a huge benefit and many other languages have since emulated this feature.

I had never considered the power of reflection or introspection until using Java. Java continues to add reflection capabilities such as method handles in Java 7 and the new java.lang.reflect.Parameter class in Java 8. The ability to programmtically access details about the internals of the virtual machine and even of running applications themselves was a concept introduced to me by Java's Java Management Extensions (JMX).

Java's emergence occurred in the era of we C++ developers (among others) grasping concepts covered in the Gang of Four's book Design Patterns: Elements of Reusable Object-Oriented Software. Java introduced features built into the language that formalized some of this book's concepts for us. In particular, the Java interface makes implementing many of the patterns outlined in that book easier. Java also included features that have led developers to make decisions about coding based on practical experience rather than simply theory. The best example I can think of is Java's introduction of checked exceptions. Whether loved or hated, Java's implementation of checked exceptions and unchecked exceptions has helped many developers to form opinions based on actual experience on those concepts.

Thanks goes to Nathan Green and Valery Silaev for also pointing out that I neglected to mention Java. Valery emphasized the same VM advantages Java touted and emphasized trust and performance gains in a virtual machine environment. Nathan had the same thought of me about the virtues of documentation generation from source code that Java made mainstream with Javadoc. Nathan also points out that the JVM supported some (minor in my opinion) languages before .NET was born. I maintain that .NET's (forced out of necessity but, as Nathan points out, not entirely successful) support of one of the world's most widely used languages (Visual Basic) being able to call libraries written in the new hotness (C#) was what really helped us to see what was practical and commercially viable on large programs.

Other JVM Languages

I'm not going to single out languages other than Java that run in the JVM in this post, but they are unquestionably influencing software development, particularly among existing Java developers. Groovy has helped me to embrace my inner scripter and Scala has helped me see more clearly the dangers of mutable state and the value of functional programming. Clojure, Kotlin, and Ceylon are also challenging the ways Java developers think and introducing new concepts, some of which even make it into Java itself. These alternate JVM languages bring many of the concepts and influences of non-Java languages (Ruby, Lisp, Erlang, etc.) to the Java developer without leaving the comfort of the JVM. The best examples of this last point are JRuby (for Ruby) and Jython (for Python).

PHP

In my post Why PHP Will Be My Next Language, I wrote about some of the reasons I was giving PHP another chance after really not liking what I saw when I first looked at it in the late 1990s. In many ways, I think that same post is a reflection of how PHP has been positively impacted by developers' experiences with other languages and cultures. There is no doubt that PHP has had a huge impact on web development. PHP has been a "gateway language" for many new web developers. It's easy mixing of presentation and server side logic has irritated some of us, but been seen as an advantage to others. It has reminded me that no rules in software development are absolute.

Numerous major web platforms are built on PHP and provide PHP APIs. The ubiquity of these necessarily means that developers cannot help but use and be influenced by PHP as they write for these platforms. It is interesting to me that the web page Past programming languages and their influences on today's languages and programming paradigms is powered by PHP even though PHP is not mentioned specifically in the article. It sounds something like a Java-oriented blog not featuring Java as one of its languages that has contributed to software development.

Thanks goes to Valery Silaev for mentioning my neglect of PHP in this original post.

Ada

The recent interview article "Security is one of the biggest problems for the IoT right now" reminded me that I missed Ada on my list. Although Ada today fits Jamie Ayre's description in that article ("[Ada]’s certainly a niche language, it’s not C, it’s not Java".), Ada was much bigger historically and has had tremendous impact on software development. AdaCore's description of Ada states, Ada is a modern programming language designed for large, long-lived applications – and embedded systems in particular – where reliability and efficiency are essential. ... Ada 95 was the first internationally standardized (ISO) Object-Oriented Language."

Erlang

Erlang is described on its main web page as "a programming language used to build massively scalable soft real-time systems with requirements on high availability." The Don't Drink Too Much Kool-Aid section of Learn Us Some Elang for Great Good! does a nice job of contrasting what Erlang is good for with what it's not as good for. Erlang's concurrency-oriented models have influenced developers and other languages. Why Erlang Matters and Why I Program in Erlang are also interesting reads about Erlang and its influence on developers.


Conclusion

Software developers today have more programming languages to choose from than ever before. No one language is best in every situation and the variety of languages with different sets of advantages and disadvantages provides the consumer (developers) with many choices. Competition is good for the consumer and has driven improvements in the languages we use. One of the advantages of working with different programming languages is the ability to learn paradigms and concepts that can be applied to some degree in the work we do even with other programming languages. Although I definitely prefer some languages over others, I recognize that all major programming languages have their faults (or situations they aren't the best fit for) and all major programming languages have their advantages (or situations where they are one of the best fits for).

Feedback Encouraged

I undoubtedly missed several important programming languages in this post and also undoubtedly missed several important features of some of the covered languages that have impacted software development in general. Feedback adding these languages or language features is greatly appreciated.

Additional Resources