Monday, November 2, 2009

Realizing That I Still Have Much to Learn

Several years ago, I was asked to rate myself on my level of expertise with different programming languages and frameworks. Several people were surprised when I did not rank myself at the highest possible level for knowledge of Java, especially when several developers with far less software development in general and far less Java experience in particular rated their own Java skills at the maximum level. I explained to them that I too would have at one time ranked myself at the highest possible level but that I had learned enough since that time to realize how much I still needed to learn. There was no way I could in good conscience rate myself at the highest level knowing how many areas of the Java ecosystem I lacked experience and depth of knowledge in. I believe there are numerous advantages to always understanding what one doesn't know (or working to discover what one doesn't know) and will outline some of these advantages in this post.


Ability to Consider New Options

When one thinks he or she already knows everything, that person has no incentive or interest in considering anything new or different than what he or she has done before. This can backfire because the same solution or approach rarely fits every problem a developer will encounter. It might seem easiest to shoehorn a particular problem into the solution we know best, but that does not make it the best or even an appropriate solution. By admitting that I may not know everything and have much still to learn, I will be more willing to listen to others' ideas and consider other perspectives. I still may end up going with my initial solution, but I will have thought out its benefits and costs and weighed them against the benefits and costs of the alternatives.


Ability to Learn New Things

If I think I know everything already, I have no need to waste time learning anything new. Learning new things can be tiring and even frustrating, but I am more apt to invest the time and effort in my own knowledge if I realize that there is so much still to learn.


Ability to Challenge My Own Assumptions and Biases

The person who knows everything (or at least thinks he or she is omniscient) has no reason wonder if what he or she is doing is correct for a given situation. The person who understands that he or she doesn't know everything is more willing to question his or her own actions and measure the results of those actions. If a course change is necessary, the person who understands his or her limitations is more likely to identify that need and do something about it. I have written before about the importance of confidence to a software developer. I think confidence is one of the most important traits of a successful software developer, but true confidence (as opposed to arrogance) does not preclude one from understanding that he or she is not necessarily always correct.


The Cost of Not Realizing There is Much More to Learn

I have seen many individuals who believe they have all the answers and make silly statements or, even worse, make unnecessarily costly decisions because of their arrogance and lack of understanding of their own limitations. By not having at least an idea of what one doesn't know, one is not able to sufficiently consider other ideas, to question the correctness of one's own decisions, and to realize the importance of learning new things.


The More We Learn, the More We Realize That We Don't Know

I have found that the more I learn and understand a particular subject, the more I realize how much more I still have to learn. It seems that I can only understand the bigger picture of a language or framework once I have begun to understand specific details of that language or framework. As I immerse myself in a new language or framework, I'm more likely to notice relevant articles posted on DZone or Reddit. Better yet, the more I learn about something, the more these blogs and articles make sense to me and the bigger the possibilities become.

As an example of this principle, consider a person learning the Java programming language. He or she may at first think only of the programming language itself and focus on keywords, syntax, and so forth. As the person gains familiarity with Java SE, he or she may start to be more exposed to Java EE principles. Similarly, the developer may start to learn about other languages on the JVM. In addition, that developer may start to learn about frameworks and libraries available for use. During all this, that developer continues to learn the Java APIs and how vast they are. What seemed like a simple language turns out to be a complex, ever-changing ecosystem.

The interesting phenomenon here is that because I have repeatedly realized how much more I still have to learn after I have learned substantially new information, I assume that I will continue to realize that I have even more to learn as I continue to learn and gain experience. In other words, the absolute amount of knowledge I would like to learn to be more effective is likely to only get larger, even as I learn new things. It's not that I realize that I need to learn more despite my current learning; rather it's precisely because I'm learning that I realize how much more I still need to learn.


Conclusion

When one understands that he or she may not be always correct, he or she is more likely to catch their own mistakes early before they are most costly, is more likely to listen to and seriously consider alternative approaches, and is more likely to keep bettering himself or herself. I am realizing that it is actually a good sign when I understand how much I still have to learn -- this often means that I'm starting to get a much better understanding of the big picture and how things fit together.

Thursday, October 29, 2009

Internet Archive WayBack Machine: Valuable Technical Reference

Have you ever bookmarked a really good technical resource, but were disappointed when you tried to access that page later and it was gone? Have you ever seen what looks like the perfect linked resource in a blog post, article, or book, but then found the referenced URL to not work? In short term cases such as an intermittent server issue or network problem, Google Cache can be an indispensable tool to see a cached version of the page. When a page has been completely removed for a long time, a web page archiving site is more helpful.

A particularly easy site archive tool to use is Internet Archive's WayBack Machine. This free online tool is very easy to use if you know the URL of the page you care about (which you would if the URL was part of a bookmark or if you clicked on a link to a site that was no longer present). You can enter the URL in the form field at the Wayback Machine page, click on the button saying "Take Me Back."



After doing the above, you see a detailed history of changes to the page at that location. This is demonstrated in the following screen snapshot.



The above screen snapshot demonstrates use of Internet Archive Wayback Machine to see a history of my page on Common Struts Errors and Their Causes that was originally posted on GeoCities, but is no longer available due to the demise of GeoCities.

Even though the page is no longer available at the GeoCities URL, its archived versions can still be viewed via the Internet Archive WayBack Machine. The following two images show what happens when one tries to access the page at its former GeoCities address and then what happens when using one of the Internet Archive WayBack Machine's archived versions.





As the screen snapshots above indicate, the page that is no longer available on GeoCities is still available via Internet Archive WayBack Machine. In my case, I have hosted this page at Google Sites and there are many other mirrored copies of it on the web, but the Internet Archive can be useful for finding pages that don't get copied or hosted on alternative sites. Because Internet Archive WayBack Machine also provides various versions of the same page, a history of a particular page can be seen.

The recent loss of GeoCities-hosted pages only one of many examples of original content being removed from the web. A relatively recent well-known example of loss of original content was the sudden and somewhat surprising online disappearance of why the lucky stiff. The next two screen snapshots show a page from the popular Why's (poignant) Guide to Ruby. The first snapshot indicates that the original page is no longer available at its original URL (http://www.poignantguide.net/ruby/chapter-1.html), but the second snapshot indicates that it is archived and accessible with WayBack Machine (at http://web.archive.org/web/20080526095452/www.poignantguide.net/ruby/chapter-1.html).





So far, I've only discussed the simple search implemented by providing the URL and clicking on the "Take Me Back" button. There are many advanced search options as well. If you have an e-mail or bookmark with a URL that no longer works, you'll often have a date on the e-mail or a date on the bookmark property of when it was created. You can use that date with WayBack Machine to find the page as of that date. This is especially useful for an easy way to recollect history.

What was big in the world of Java in late 2004? To find this out, I could look at archives for some major players in the Java world. For example, the java.sun.com page on the last day of 2004 looked like that shown in the next screen snapshot:



We can see from the above screen snapshot (I had entered http://web.archive.org/web/20041231/java.sun.com/ with a day but no time, but it resolved to http://web.archive.org/web/20041231092116/java.sun.com/ with a day and appropriate time) that big topics at the end of 2004 included early access to binaries and source of Java SE 6 (then still called as J2SE 6 or Mustang) and NetBeans 4.0.

As a final example, I'll look at something from the very early days of Java. The URL http://web.archive.org/web/19970211220056/www.sun.com/sunworldonline/swol-10-1995/swol-10-javadigest.html provides an interesting article from SunWorld Online called Java users reveal their habit. This makes for very interesting historical perspective for those of us in the Java community. For those of us who have been around since the public inception of Java, it is a reminder that applets were once the "big thing" in the Java world. For those who are not familiar with the early days of Java, it can provide an interesting perspective on how far things have come (and how much some things are still the same).

Assuming that the deal for Oracle to acquire Sun Microsystems goes through, there is some question about what will happen to the wealth of Java resources available online at domains such as http://java.sun.com/ (such as the JDK 6 Documentation). These articles and other documents will almost assuredly continue to exist (even if at a different URL that includes "oracle" in its name), but it is still comforting to know that the archived versions should also be available via the WayBack Machine.

There are many valuable benefits to having old web pages still available after their deletion and having the ability to see older versions of a particular web page. When one runs into the all-too-common frustration of finding a bookmark or link that is no longer valid, the Internet Archive WayBack Machine is a very welcome tool. However, such power can also be abused. Some articles that talk about people who are not too happy with the power of the WayBack Machine include Internet Archive Sued Over WayBack Machine and Internet Archive Settles Suit Against WayBack Machine.

As an interesting side note, there is a Java-based, open source implementation of the WayBack Machine called wayback.


Conclusion

There is no question that the ability to link documents via hyperlinks is one of the main reasons for the success of HTTP and the World Wide Web. It is very convenient to click on links in bookmarks, e-mail messages, articles, blogs, and even type in URLs from books and go directly to the referenced site. On the other hand, one of the greatest disappointments when using the web is when a hyperlink is no longer valid. Although a search engine might be able to tell you a page's new location (or the location of a mirror or copy), or Google Cache might be used to see a cached version of a page that is temporarily down, a tool like the Internet Archive WayBack Machine is sometimes what is needed to see a page that is no longer otherwise available. In cases where the page still exists, but information that was previously available has been removed, WayBack Machine's ability to see historical versions of that particular page is very useful. In many ways, using WayBack machine definitely feels like time travel.

Wednesday, October 28, 2009

Reocities: GeoCities Rising from the Ashes

I previously wrote about the potential loss of historical technical details as a result of the demise of Yahoo! GeoCities. I listed several useful technical pages hosted on GeoCities that might be lost. Others have also pointed out that GeoCities provided a perspective of the early days of personal web pages with profound value for those interested in studying the history of the web.

I read with interest Jennifer Van Grove's post One Man's Quest to Bring GeoCities Back from the Dead. The endeavor she highlights, instantiated as the ReoCities site, is interesting enough because of the salvaged data of potentially significant value. Perhaps even more interesting, though, is the technical challenge associated with this and the approach being used. More details on this can be found in The Making Of, a story of stress and scripting.

According to the Wikipedia entry for GeoCities, other efforts to archive potentially valuable data hosted on GeoCities include Internet Archive and InternetArchaeology.

Monday, October 26, 2009

Maintaining a Software Development Library (Books)

For as long as I can remember, I have always loved books. When I was growing up and my parents would offer to buy my brothers and me something at the store, I'd almost always select some fictional book while my brothers would select toys. As an adult, I don't read as much fiction as I'd like, but I do buy and read (at least portions) of a lot of technical books. I've got technical books strewn around the house in several different book cases in several different rooms. My wife asks me to take more of them to work, but I have my two long book shelves at work filled as well. In this blog post, I look at why I value these books (versus the information freely available on the web), how I get many of them for really low prices, and how I finally determine when a book has gone beyond usefulness to uselessness and often even to being a hindrance.


Why Books?

With the prevalence of blogs and online articles, why do we even need technical books? I have found that blogs and articles can be superior to books in terms of cutting-edge knowledge and in terms of strange corner cases. However, books are typically better at providing "big picture" introduction to a topic and at providing in-depth thorough coverage of a topic. Books can also be taken just about anywhere, though e-books are becoming more portable with devices such as the Amazon Kindle. I still prefer the ability to write notes in my book and I find that my memory of a certain concept or description seems to be better with physical associations I make mentally. Books often provide more consistent and thorough coverage of a topic than can be covered in a collection of blog posts and articles, even when written by the same individual or team.


Acquiring the Technical Book

I have purchased some real stinkers when I have not adequately researched what I was purchasing. Fortunately, I have gotten better at picking better technical books. There are several factors that aid in this process. Reviews on sites like Amazon.com can be insightful, especially when reviewers express why they like or dislike a particular book. There are also many bloggers who post reviews of technical books. Furthermore, many users groups also provide book reviews. Asking fellow developers and colleagues about the books they own and/or have read can also be enlightening. It is best to consider a wide set of reviews rather than a single review when trying to determine whether to purchase a particular book.

I have sometimes made a decision to purchase a book after borrowing it from a colleague or from the library. This was the case with the Second Edition of Effective Java. I was "on the fence" about purchasing the Second Edition (until it fell in price on the Amazon Marketplace at least) until I borrowed a colleague's Second Edition and realized how much was added in that edition. I have also found several highly useful books and some not-so-useful books after borrowing them from the library and evaluating them. In a few cases, I have gotten the tip or piece of knowledge I needed from a particular book during the period I had it borrowed from the library and did not need to purchase it after borrowing it.

Many publishers offer sample chapters that allow one to preview a portion of a technical book and this can provide insight to the author's writing style and level of detail. Entire older editions of some books are available online. For example, Bruce Eckel makes old editions of some of his books available online. O'Reilly has its Open Books Project with online editions of books that can be reviewed (and sometimes this is the only way to easily access out of print books). If you like what you read there, you can purchase the latest edition to get up-to-date information.

Speaking of older editions, there can be times when acquiring an older edition of a particular book is satisfactory. An older edition can be much less expensive than the latest edition. Traditional and online bookstores will deeply discount the older editions before the new editions come out. Depending on how important the information in the new edition is, considering an older edition can be a useful approach.

When I purchase a technical book, I often first consider Amazon Marketplace. The Amazon Marketplace has the advantage of being hosted directly on Amazon.com and allowing the purchase to be made via Amazon using one's Amazon account. This implies no need for a special account and means that Amazon handles the financial transaction. I am more comfortable trusting my credit card information with a single vendor (Amazon) than with each individual third-party vendor that sells on Amazon Marketplace. My experience is that the new or used books purchased through Amazon Marketplace often arrive quickly and in outstanding shape.

There are a couple things to be aware of when using Amazon Marketplace. For one, shipping and handling is added to the price and typically purchasing $25 worth of merchandise does not mean free shipping when purchasing through the Marketplace. There are times when the fulfillment is through Amazon on a Marketplace purchase and in some of those cases the purchase can use the free shipping with $25 purchase option or Amazon's other prime shipping deals. There are times, especially for newer and more popular technical books, when it costs almost as much or even more to purchase the Marketplace book and pay the shipping (often $3.99 per book) as it costs to buy the book new directly from Amazon with free shipping.

A second consideration with purchasing books on Amazon Marketplace is that the third-party vendor typically arranges the actual administration of the order fulfillment. This can mean a delay in delivery, though it varies widely from very quick vendors to very slow vendors. If you need the book in the next several days, you might want to consider another option.


Using the Technical Book

Although I love books in general and technical books in particular, I rarely read technical books cover to cover. I have only read portions of most of my technical books. In some cases, I have read the entire book several times, but never cover-to-cover. I have read a few technical books cover-to-cover, but that is the exception rather than the norm.

I like to read portions of many of these books during small amounts of available free time. This can include waiting for a car to be serviced, waiting at a doctor's office, waiting for a train on railroad tracks, etc. I almost always have a book with me in the car for such situations. I also read portions of books directly related to whatever I'm working on at the time.

A technical book is often used as a reference and, in such cases, a good index is highly valuable. I have found that a really good index can turn a mediocre book into a trusted resource. Even the best indexes often lack every term I find myself frequently looking up in the book. Because of this, I have gotten in the habit of adding my own index entries in my most-used books for terms and pages that I expect I may want to look up again in the future.

Besides writing in my own index entries, I also often write notes in my books referencing other sections of the book that are related. I like to record any substantive changes on relevant pages in the book to help address obsolescence that is unavoidable with technical books. For example, the Spring Framework Reference is almost always going to be more current than a printed book can ever hope to be. Therefore, my favorite Spring book has many notes in it adding new or changed features in the Spring Framework that I have found out about via blogs, articles, or reading the Spring reference.


Saying Goodbye

Because I enjoy books so much, it can be difficult to part with one, even when it has lost its usefulness. For one thing, there is always the possibility that I might need it again. It can be difficult to admit that I probably won't. Another hindrance to getting rid of a particular book occurs when it is outdated, but I hesitate to invest in a newer edition or improved version. There are also logistical issues such as how to determine when a book has lost its usefulness and deciding on the best way to get rid of it (paper recycling, book use recycling, trash, etc.).

When a book gets so old that it actually contains information that is no longer accurate, it can be risky to use. This is because it can teach incorrect principles that have to be unlearned and can waste a lot of time trying to figure out why something doesn't work as described in the book. In a worst-case scenario, one might even be dissuaded from using a particular technology because of frustrations that are a direct result of using an obsolete and/or incorrect book.

Some books are easier to get rid of because the covered technologies are obviously obsolete. For example, I shouldn't have much trouble getting rid of my book on J# because it is extremely unlikely at this point that I'll ever need that book. Even better examples are books on specific versions of products or implementations that are no longer available or are no longer regularly used.

With some still-popular languages and frameworks it can be more difficult to determine when a book on the subject has passed its useful life. For example, it is my opinion (assuming one is developing in JDK 1.4, J2SE 5, or Java SE 6) that any book on Java that was written before JDK 1.1 is not worth reading or using. Although a book on JDK 1.2 or JDK 1.3 might be a little better, I really don't think most Java books focused on a version of Java prior to JDK 1.4.2 are worth keeping (or at least regularly referencing). JDK 1.4 was a "game changer" in the world of Java development and it is my opinion that any Java book with real usefulness must address at least that version. Similarly, any Flex book covering Flex 2 or Flex 3 might be fine, but any book addressing Flex before Flex 2 (Flex 1.0 or Flex 1.5) is generally not worth keeping or using.

I typically am too much of a cheapskate to purchase a newer edition of the same book unless the new edition offers enough to justify its purchase. An example of when this has been the case is Effective Java. What makes this example interesting is that even after purchasing the Second Edition, I have retained my First Edition copy. The reason for this is that the First Edition is still largely valid and I like to have it around when I have loaned my Second Edition to someone else or have left it somewhere other than my work desk. The point of this is that even purchasing a newer edition of a particular book may not necessarily mean it is time to get rid of the older edition.

When the time comes to part with a technical book, there are several options. If the book is still relevant (not usually the case for me because I wait until the book is completely useless to anyone to part with it), it can be sold online (such as through the previously mentioned Amazon Marketplace, eBay, or other used book selling venue). A book with some remaining relevance might also be donated to a library, a school, or to fellow developers who are working with the language or technology and don't have a better book (especially if they are using an older version to which the book is more applicable). If a book has become so obsolete that it has no value to anyone, the best remaining option is to have its materials recycled.

There are several good blog posts on getting rid of technical books. These include Don Demsak's Recycling Technical Books, Book Recycling, and How Can I Reuse or Recycle Old Books? (see feedback comments as well), and How Book Recycling Can Help the Environment.


Ideas for Good Technical Books

Looking for ideas for some good technical books to add to your personal library? Here are some lists of others' favorite technical books:
StackOverflow: 'Must Have' Books on Your Bookshelf (2009)
What Is The Single Most Influential Book Every Programmer Should Read? (2008)
Top 100 Best Software Engineering Books, Ever (2008)
The Best Books Every Programmer Should Read (2006)
Coding Horror: Recommended Reading for Developers (2004)
Elliotte Rusty Harold's Ten Must-Have Technical Books (2003)


Conclusion

A technical book can be a valuable resource in improving one's skills. However, most of us want to be careful without our money and (perhaps even more careful) with our time. We want to spend our money and time as efficiently as possible. In this blog post, I have recorded some of the things I have learned to improve the efficiency of money and time I invest in acquiring, using, and finally retiring of technical books.

Firefox 3.6 Requires Java SE 6 Update 10

Java SE 6 Update 10 was a significant release despite its version numbering indicating a minor release. Among other advancements, Java SE 6 Update 10 introduced the Next-Generation Java Plug-in for a better Java applet experience. It has now been announced that Firefox 3.6 (Namoroka) will require this next-generation plug-in. Users can access the web page at http://java.com/en/download/help/testvm.xml to test the version of Java supported on a particular machine. The Firefox 3.6 for Developers page specifies advancements in support for Cascading Style Sheets, HTML, JavaScript, DOM, and XPath.

Sunday, October 25, 2009

RMOUG Training Days 2010 Abstracts: Groovy, REST, and Better UIs

As I noted in my previous post, my two abstracts have been accepted by the Rocky Mountain Oracle Users Group (RMOUG) for presentation at Training Days 2010. I have also learned that Bill Jackson's abstract for "Ten Easy Ways To Build a Better GUI" has been accepted as well. I will include the abstracts for my two presentations and for Bill's presentation later in this post.

I am eager to present these two presentations because they are inspired by the presentations that I had planned to present at Colorado Software Summit 2009. Incidentally, that conference would have started tonight with the annual Sunday evening reception famous for its good food and interesting conversation. It was a great way to casually and comfortably kick off an absolutely terrific conference. I was sad to hear about the end of this conference and don't like thinking about what I am missing this week. It certainly would have been nice to be getting my brain crammed full of software development concepts and ideas this week in beautiful Keystone, Colorado. As I stated, however, the opportunity to present presentations at RMOUG Training Days 2010 similar to what I had planned for CSS 2009 is a positive one.

My two abstracts that were accepted for RMOUG Training Days 2010 are "Applied Groovy: Scripting for Java Development" and "RESTful Java." The abstracts for these two presentations are (may differ slightly from what will appear in the conference materials):


Applied Groovy: Scripting for Java Development

As a dynamic language that runs on the JVM and can be used anywhere the Java programming language is used, Groovy is a great choice for building, testing, and maintaining Java SE and EE applications. This presentation briefly summarizes some basics of Groovy and advantages of using Groovy before moving onto demonstrating how to use Groovy to improve the ability to build and test standard and enterprise Java applications. Although the basics of Groovy will be covered initially in the presentation for those who have not used Groovy previously, most of the syntax and other features of Groovy covered in this presentation will be presented in conjunction with use of Groovy in the building and testing of applications for the Java platform.


RESTful Java

The Java platform provides many types of support for building REST-based web services and REST-compliant clients. This presentation will briefly summarize the main principles of the Representational State Transfer style of web services before covering several of the most popular Java-based approaches for working with REST. The presentation will focus on JSR 311 (“JAX-RS: The Java API for RESTful Web Services”), Jersey (the JSR 311 reference implementation), Restlet, and Enunciate while also covering other useful tools related to REST-oriented development with Java.


Bill Jackson's abstract is called "Ten Easy Ways to Build a Better GUI." His abstract is shown next and, as its name implies, focuses on Graphical User Interfaces (GUIs).


10 Easy Ways to Build a Better GUI

In the world of graphic user interfaces, form nearly always follows function. From Dilbert jokes about GUIs designed by engineers to MySpace’s reputation for ugly pages it’s clear that designing attractive, useful, and well thought-out GUIs is much easier said than done.

However, positive examples in the commercial world such as Apple’s well-earned reputation for stylish products show just how much impact a well designed user interface can have. This presentation will cover 10 basic steps for building more intuitive, attractive, and useful user interfaces. The discussion will include issues such as usability, data presentation, form layout, color selection, icon acquisition, and a host of other issues that will help attendees to understand the basic steps to making programs that users actually like. The benefits of these skills go beyond the aesthetic issues to help raise user productivity and product longevity. The presentation will not require any specific programming knowledge and will apply to desktop applications and web pages alike



My presentations planned for RMOUG Training Days 2010 will be changed to some degree because of the different venue and different audience characteristics. The Groovy presentation is conceptually almost exactly what I planned for Colorado Software Summit except that I was going to speak on JRuby there. The RESTful Java presentation will be 60 minutes at RMOUG Training Days 2010 rather than the 90 minutes it would have been at Colorado Software Summit 2009. Because of the shorter duration, it will necessarily be less detailed at Training Days, but I think that may fit the different audience better anyway. I will focus on basics of REST and then cover at a high level (with some API details) how to apply Java tools and frameworks to build REST-based applications.

Rocky Mountain Oracle Users Group Training Days 2010 will take place February 16-18, 2010, at the Colorado Convention Center in Denver, Colorado.

Saturday, October 24, 2009

Java SourceVersion and Character

The SourceVersion class provides information on Java source versions and can provide some interesting details, including demonstration of terminology covered in the Java Language Specification. In this blog posting, I look briefly at some of the more interesting observations one can make using this class that was introduced with Java SE 6 in conjunction with the Java long-timer class Character.

The SourceVersion class provides several handy static methods for ascertaining details about the source version of the current Java runtime. The methods SourceVersion.latest() and SourceVersion.latestSupported() provide details regarding the latest source versions that can be "modeled" and "fully supported" respectively.

The following code snippet demonstrates these two methods in action.


out.println("Latest source version that can be modeled: ");
out.println("\tSourceVersion.latest(): " + SourceVersion.latest());
out.println("Latest source version fully supported by current execution environment ");
out.println("\tSourceVersion.latestSupported(): " + SourceVersion.latestSupported());


The output from running this code is shown next.



As the code example and corresponding output above indicate, the currently supported modeled version and currently fully supported versions are easily accessible. Although the SourceVersion class was introduced with Java SE 6, it has been built to be support future versions of Java. Not only does the Javadoc documentation state that "additional source version constants will be added to model future releases of the language," but the SourceVersion.values() method also provides all supported version enums. A code example and associated output are shown next to demonstrate this method in action.


out.println("SourceVersion enum Values:");
final SourceVersion[] versions = SourceVersion.values();
for (final SourceVersion version : versions)
{
out.println("\t" + version);
}




The Javadoc documentation tells us the meanings of the various enum values shown in the above output. Each represents a different "source version of the Java programming language" and the platform version it is associated with. As shown earlier, the RELEASE_6 is associated with Java SE 6, RELEASE_5 is associated with J2SE 5, RELEASE_4 is associated with JDK 1.4, RELEASE_3 is associated with JDK 1.3, RELEASE_2 is associated with JDK 1.2, RELEASE_1 is associated with JDK 1.1 and RELEASE_0 is associated with "the original version." The Javadoc documentation for Java SE 7 indicates that SourceVersion.RELEASE_7 is supported in Java SE 7.

The SourceVersion class provides three static methods that each indicate whether a provided CharSequence is an identifier, keyword, or name. The three methods that allow one to dynamically determine if a particular CharSequence fits one or more of the types identifier, name, or keyword are (respectively) SourceVersion.isIdentifier(), SourceVersion.isName(), and SourceVersion.isKeyword().

Using these methods allows one to determine if a particular string is reserved as a keyword, is even considered a valid identifier, and if a string that is a valid identifier is not a keyword and is thus a valid name. The isName() method returns true for a "syntactically valid name" that is not also a keyword or literal. The isKeyword() method indicates if the provided string is one of the keywords listed here.

I have run many different strings of various combinations of these three types in the following code.


public static void printIdentifierTest(final String stringToBeTested)
{
out.println(
"Is '" + stringToBeTested + "' an identifier? "
+ SourceVersion.isIdentifier(stringToBeTested));
}

public static void printKeywordTest(final String stringToBeTested)
{
out.println(
"Is '" + stringToBeTested + "' a keyword? "
+ SourceVersion.isKeyword(stringToBeTested));
}

public static void printNameTest(final String stringToBeTested)
{
out.println(
"Can '" + stringToBeTested + "' be used as a name? "
+ SourceVersion.isName(stringToBeTested));
}

public static void printTests(final String stringToBeTested)
{
out.println("\n=============== " + stringToBeTested + " ===============");
printIdentifierTest(stringToBeTested);
printKeywordTest(stringToBeTested);
printNameTest(stringToBeTested);
}

public static void printTests(
final String stringToBeTested,
final String alternateHeaderString)
{
out.println("\n=============== " + alternateHeaderString + " ===============");
printIdentifierTest(stringToBeTested);
printKeywordTest(stringToBeTested);
printNameTest(stringToBeTested);
}

/**
* Main function for demonstrating SourceVersion enum.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
final String dustinStr = "Dustin";
printTests(dustinStr);
final String dustinLowerStr = "dustin";
printTests(dustinLowerStr);
final String instanceOfStr = "instanceof";
printTests(instanceOfStr);
final String constStr = "const";
printTests(constStr);
final String gotoStr = "goto";
printTests(gotoStr);
final String trueStr = "true";
printTests(trueStr);
final String nullStr = "null";
printTests(nullStr);
final String weirdStr = "/#";
printTests(weirdStr);
final String tabStr = "\t";
printTests(tabStr, "TAB (\\t)");
final String classStr = "class";
printTests(classStr);
final String enumStr = "enum";
printTests(enumStr);
final String assertStr = "assert";
printTests(assertStr);
final String intStr = "int";
printTests(intStr);
final String numeralStartStr = "1abc";
printTests(numeralStartStr);
final String numeralEmbeddedStr = "abc1";
printTests(numeralEmbeddedStr);
final String dollarStartStr = "$dustin";
printTests(dollarStartStr);
final String underscoreStartStr = "_dustin";
printTests(underscoreStartStr);
final String spacesStartStr = " dustin";
printTests(spacesStartStr, " dustin (space in front)");
final String spacesInStr = "to be";
printTests(spacesInStr);
}


When the above code is executed the output shown next is generated.


=============== Dustin ===============
Is 'Dustin' an identifier? true
Is 'Dustin' a keyword? false
Can 'Dustin' be used as a name? true

=============== dustin ===============
Is 'dustin' an identifier? true
Is 'dustin' a keyword? false
Can 'dustin' be used as a name? true

=============== instanceof ===============
Is 'instanceof' an identifier? true
Is 'instanceof' a keyword? true
Can 'instanceof' be used as a name? false

=============== const ===============
Is 'const' an identifier? true
Is 'const' a keyword? true
Can 'const' be used as a name? false

=============== goto ===============
Is 'goto' an identifier? true
Is 'goto' a keyword? true
Can 'goto' be used as a name? false

=============== true ===============
Is 'true' an identifier? true
Is 'true' a keyword? true
Can 'true' be used as a name? false

=============== null ===============
Is 'null' an identifier? true
Is 'null' a keyword? true
Can 'null' be used as a name? false

=============== /# ===============
Is '/#' an identifier? false
Is '/#' a keyword? false
Can '/#' be used as a name? false

=============== TAB (\t) ===============
Is ' ' an identifier? false
Is ' ' a keyword? false
Can ' ' be used as a name? false

=============== class ===============
Is 'class' an identifier? true
Is 'class' a keyword? true
Can 'class' be used as a name? false

=============== enum ===============
Is 'enum' an identifier? true
Is 'enum' a keyword? true
Can 'enum' be used as a name? false

=============== assert ===============
Is 'assert' an identifier? true
Is 'assert' a keyword? true
Can 'assert' be used as a name? false

=============== int ===============
Is 'int' an identifier? true
Is 'int' a keyword? true
Can 'int' be used as a name? false

=============== 1abc ===============
Is '1abc' an identifier? false
Is '1abc' a keyword? false
Can '1abc' be used as a name? false

=============== abc1 ===============
Is 'abc1' an identifier? true
Is 'abc1' a keyword? false
Can 'abc1' be used as a name? true

=============== $dustin ===============
Is '$dustin' an identifier? true
Is '$dustin' a keyword? false
Can '$dustin' be used as a name? true

=============== _dustin ===============
Is '_dustin' an identifier? true
Is '_dustin' a keyword? false
Can '_dustin' be used as a name? true

=============== dustin (space in front) ===============
Is ' dustin' an identifier? false
Is ' dustin' a keyword? false
Can ' dustin' be used as a name? false

=============== to be ===============
Is 'to be' an identifier? false
Is 'to be' a keyword? false
Can 'to be' be used as a name? false



The above output demonstrates that a valid name must be a valid identifier without being a keyword. A keyword must be a valid identifier, but not all identifiers are keywords. Some string values that are not keywords or reserved words are not even identifiers because they don't meet the rules of Java identifiers.

The examples above indicate that we cannot use a name for a variable or other construct that begins with a numeral, but we can use $ and _ for the first character in a name. Another way to determine this is through use of the static method Character.isJavaIdentifierStart(char). The following code snippet demonstrates this along with the similar method Character.isJavaIdentifierPart(char), which returns true if the provided character can be in the name anywhere other than the first character.


public static void printTestForValidIdentifierCharacter(
final char characterToBeTested)
{
out.println(
"Character '" + characterToBeTested
+ ( Character.isJavaIdentifierStart(characterToBeTested)
? "': VALID "
: "': NOT VALID ")
+ "FIRST character and "
+ ( Character.isJavaIdentifierPart(characterToBeTested)
? "VALID "
: "NOT VALID ")
+ "OTHER character in a Java name.");
out.println( "\tType of '" + characterToBeTested + "': "
+ Character.getType(characterToBeTested));
}

public static void demonstrateCharacterJavaIdentifierStart()
{
out.println("\nTEST FOR FIRST AND OTHER CHARACTERS IN A VALID JAVA NAME");
printTestForValidIdentifierCharacter('A');
printTestForValidIdentifierCharacter('a');
printTestForValidIdentifierCharacter('1');
printTestForValidIdentifierCharacter('\\');
printTestForValidIdentifierCharacter('_');
printTestForValidIdentifierCharacter('$');
printTestForValidIdentifierCharacter('#');
printTestForValidIdentifierCharacter('\n');
printTestForValidIdentifierCharacter('\t');
}


The output from the above appears below.


TEST FOR FIRST AND OTHER CHARACTERS IN A VALID JAVA NAME
Character 'A': VALID FIRST character and VALID OTHER character in a Java name.
Type of 'A': 1
Character 'a': VALID FIRST character and VALID OTHER character in a Java name.
Type of 'a': 2
Character '1': NOT VALID FIRST character and VALID OTHER character in a Java name.
Type of '1': 9
Character '\': NOT VALID FIRST character and NOT VALID OTHER character in a Java name.
Type of '\': 24
Character '_': VALID FIRST character and VALID OTHER character in a Java name.
Type of '_': 23
Character '$': VALID FIRST character and VALID OTHER character in a Java name.
Type of '$': 26
Character '#': NOT VALID FIRST character and NOT VALID OTHER character in a Java name.
Type of '#': 24
Character '
': NOT VALID FIRST character and NOT VALID OTHER character in a Java name.
Type of '
': 15
Character ' ': NOT VALID FIRST character and NOT VALID OTHER character in a Java name.
Type of ' ': 15


Because the Character.getType(char) method has been with us for quite a while and predates the J2SE 5-introduced enum construct, this method returns primitives integers. One can refer to Java's Constant Field Values to determine what each of these constants stand for.

To make the above example's output a little more readable, I have added a simple "converter" method that converts the returned int to a more readable String. I have only added switch cases for the integers returned from my example, but one could add cases for all supported types represented by different integers.


public static String extractReadableStringFromJavaCharacterTypeInt(
final int characterTypeInt)
{
String characterType;
switch (characterTypeInt)
{
case Character.CONNECTOR_PUNCTUATION :
characterType = "Connector Punctuation";
break;
case Character.CONTROL :
characterType = "Control";
break;
case Character.CURRENCY_SYMBOL :
characterType = "Currency Symbol";
break;
case Character.DECIMAL_DIGIT_NUMBER :
characterType = "Decimal Digit Number";
break;
case Character.LETTER_NUMBER :
characterType = "Letter/Number";
break;
case Character.LOWERCASE_LETTER :
characterType = "Lowercase Letter";
break;
case Character.OTHER_PUNCTUATION :
characterType = "Other Punctuation";
break;
case Character.UPPERCASE_LETTER :
characterType = "Uppercase Letter";
break;
default : characterType = "Unknown Character Type Integer: " + characterTypeInt;
}
return characterType;
}


When the integers returned from Character.getType(char) in the example two listings ago are run through this switch statement, the revised output appears as shown next.


TEST FOR FIRST AND OTHER CHARACTERS IN A VALID JAVA NAME
Character 'A': VALID FIRST character and VALID OTHER character in a Java name.
Type of 'A': Uppercase Letter
Character 'a': VALID FIRST character and VALID OTHER character in a Java name.
Type of 'a': Lowercase Letter
Character '1': NOT VALID FIRST character and VALID OTHER character in a Java name.
Type of '1': Decimal Digit Number
Character '\': NOT VALID FIRST character and NOT VALID OTHER character in a Java name.
Type of '\': Other Punctuation
Character '_': VALID FIRST character and VALID OTHER character in a Java name.
Type of '_': Connector Punctuation
Character '$': VALID FIRST character and VALID OTHER character in a Java name.
Type of '$': Currency Symbol
Character '#': NOT VALID FIRST character and NOT VALID OTHER character in a Java name.
Type of '#': Other Punctuation
Character '
': NOT VALID FIRST character and NOT VALID OTHER character in a Java name.
Type of '
': Control
Character ' ': NOT VALID FIRST character and NOT VALID OTHER character in a Java name.
Type of ' ': Control


The SourceVersion class is useful for dynamically determining information about the Java source code version and the keywords and valid names applicable for that version. The Character class also provides useful information on what a particular character's type is and whether or not that character can be used as the first character of a name or as any other character in a valid name.