Showing posts with label NAME. Show all posts
Showing posts with label NAME. Show all posts

Saturday, 15 September 2012

Java's File Names and Class Names

Java is picky about the file names you use.

Each source file can contain one public class. The source file's name has to be the name of that class. By convention, the source file uses a .java filename extension (a tail end of a file name that marks the file as being of a particular type of file.)

So, for a class declared as such:
public class HelloWorld{
...

The file it is stored in should be named HelloWorld.java.

The capitalization should be the same in both cases. Some operating systems don't notice whether file names are capitalized or not. It doesn't matter, you should be in the habit of using the correct capitalization in case you work on a system that does care about capitalization.

When you compile your file with javac, you pass the full file name to javac:

javac HelloWorld.java

Let's say we save the file under a different name. We write the following program:

public class HelloThere{
    public static void main(String arg[]){
        System.out.println("Hello There.");
    }
}

Then we save it as HelloWorld.java, and try to compile it:
>javac HelloWorld.java
FileName.java:1: class HelloThere is public, should be declared 
in a file named HelloThere.java
public class HelloThere{
       ^
1 error


Java lets us know that it won't compile until we rename the file appropriately (according to its rules.)

So let's rename the file. Let's call it HelloThere.javasource. Seems a bit more explicit than just .java, right? Let's run the compiler:

>javac HelloThere.javasource 
error: Class names, 'HelloThere.javasource', are only accepted 
if annotation processing is explicitly requested
1 error

Java's still not happy with us. Annotation processing? That's when we include extra information in the program about the program itself. We're not bothering with that just now. So we should just name the file HelloThere.java, and not get fancy with our file names.

But, under the right circumstances, javac does allow file name extensions other than .java. That's why we always type in the full file name, including .java, when we use javac. We say 'javac HelloThere.java', not just 'javac HelloThere'. Javac can't assume that we mean a .java file, though that's what it will usually be.

The Class File

Once we make javac happy with a proper file name, and a program with no errors, javac produces a new file. This file will have the original file name, but with .java replaced with .class. This is your bytecode file, the file that the Java Virtual Machine can run.

When we run the program with Java, we're running the .class file. In the case of HelloThere, we're running the HelloThere.class file. But we don't type in the full file name. Why?

Unlike javac, java requires a .class file. That's all it will work with. There's no opportunity to have a different extension to the file name. So it assumes the .class part of the file name. But that's not the whole story.

If you add .class yourself, here's what you'll get:
>java HelloThere.class
Exception in thread "main" java.lang.NoClassDefFoundError: 
 HelloThere/class
Caused by: java.lang.ClassNotFoundException: HelloThere.class
 at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

Pretty ugly. What we're actually doing when we type "java HelloThere" is telling Java to run the class HelloThere. Java assumes that it will find this in a file called "HelloThere.class", so that's what it's looking for first.

We're not telling Java to run the file HelloThere.class, we're telling it to run the class HelloThere, which it expects to find in the file HelloThere.class.

But what if we ask for another class that doesn't have its own .class file?

Just for fun, let's change HelloThere.java like this, and see what happens:

public class HelloThere{
 public static void main(String[] arg){
  System.out.println("Hello.");
 }
}

class HelloZoik{
 public static void main(String[] arg){
  System.out.println("Zoiks!");
 }
}

After we edit it, we compile with 'javac HelloThere.java' and hold our breath.

Hurray! No errors!

Now we have a second class, HelloZoik, in the HelloThere.class file. Can Java find it?

Let's try:

 java HelloZoik
Zoiks!

It worked! Java found our class inside HelloThere.class.

This shows it's not the file name that we're calling with the 'java' command, it's the class name.

If Java doesn't find the class inside a file with the same name as the class followed by .class, it'll look in the other .class files available.

Friday, 14 September 2012

Making Java Signatures Simple

Methods have names. For example, System.out.println() is usually called "print line", though we'd probably say "system-out-print line" for it as I've written it here.

Unfortunately, the word "name" doesn't have a technical meaning. And even if we gave it one, it might lead to misunderstanding when we're switching back between technical terms and nontechnical ones. So there's a technical term for names of methods in Java: signatures.

The way we've used "name" above refers to the same thing as the Java term "simple signature." The simple signature of a method is its text name, ignoring everything in the parentheses, its return type, and so on. So println() and println(String) have the same simple signature.

The full signature, which is what we mean when we just say "signature", includes the full typing of the method and its parameters. So the full signature includes the type or class of everything in the parentheses of the method as well as the name of the method. This is what Java looks at when it's compiling.

That's why you get a runtime error if you do the following:

public static void main(){
...


The Java compiler will compile this just fine. It will create a .class file with a method that's got the signature main().

Then when you try to run it, the JRE will look for a method with the signature main(String[]), that is, a method with the text name main followed by a parameter list that includes an array of strings. If the array of strings isn't there, it doesn't match the signature that the JRE is looking for. So you get an error when you try to run your program. This will also happen if you do this:

public static void main(String arg){
...


You've got a method whose signature is main(String) not main(String[]), that is, its parameter is a String, not an array of Strings.

An example of methods that have the same name but different signatures are the constructor methods for the Color class. You can create a new Color in any of several different ways:

Color(int r, g, b)
Color(int r, g, b, a)
Color(int rgb)
Color(float r, g, b)

and so on.

In the first we give the constructor three different integer values for the red, green, and blue values of the new Color. In the second we give four integer values--the same three as before plus an alpha (transparency) value. Or we can pass one integer value that has all three of the red, green, and blue values in one number. Or we can pass separate red, green, and blue values as floating point numbers rather than integers. There are more ways, yet.

While all these constructors have the same name, or simple signature ("Color"), they each have a different signature based on their parameter list. That way Java is able to tell them apart, and know what value types it should expect to work with. That way if you give two values as integers, and a third as a floating point value Java will realize it doesn't know how to deal with that and recognize an error in the code.

That means when you're calling a method, and the compiler spits it out and says it's not found you need to make sure you've:
  1. spelled the name right,
  2. got the right type and number of parameters,
  3. and imported the appropriate packages and classes.