The error I get is exactly the error specified in:
http://java.syntaxerrors.info/index.php?title=Own_file
(class must be defined in its own file.)
but they don't give a solution there how to solve it, other than just having a file per public class.
Thank you, eclipse, for making me do this, but this is not mandatory in Java. Is there a way to get rid of this error?
Yes, it is mandatory in Java. Each public class has to be in a separate file named exactly the same way as the class.
See this question about it. The Java language specification writes that this is not 100% mandatory for compilers, but they usually do that. And since it is a good thing, and is noted in the spec, all compilers do it.
When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav)
If you want to have multiple classes in the same file, that's a different story. You can do it in two ways:
declare them as package-private classes with class Foo after the body of the main class. You can have any number of non-public classes in the same file
declare them as static inner classes: public static class InnerFoo inside the main class body. That way they will be visible to other classes by FooClass.InnerFoo
Related
I know that the name of the public class declared in a java file must be same as its file name. But I wonder how this is not giving me a compilation error, rather it is running successfully.
class Foo //<-- this can be any name...
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
I know that the default access is package private. For the above program, the class name and the file name need not be same. It is executing correctly, rather than a compiler error.
Can anyone throw some light? Thank you.
EDIT:
Now I get it! But another question struck me. What happens when there are two such classes in the same file?
Well, I thought a .class file will be generated out of the class that has implemented main method. There wasn't any compilation error, but to my surprise there wasn't any .class file generated either. Why is that so?
Yes, that's absolutely fine. Even for public classes, this is a compiler-specific optional restriction.
From section 7.6 of the JLS:
If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
Note the second bullet point - when your class isn't public, this restriction isn't applicable.
EDIT: From the updated question...
What happens when there are two such classes in the same file?
Class files are generated based on class names. The presence of a main method is completely irrelevant to this, as is the original source file name. A class file certainly should have been generated if compilation succeeded. Without sample code to reproduce the problem, we can't tell what happened really.
Your observation is correct. If the class is not public, the name of the class does not need to match the file name. When you don't have a public class in your file, you can name your file as you like.
If you say have a source file Test003.java and you define in it
two non-public classes AAA and BBB, there are no compilation
errors and two class files are generated: AAA.class and BBB.class.
So all is good.
01/20/2014 06:27 AM 238 AAA.class
01/20/2014 06:27 AM 238 BBB.class
Only for example lets consider the class ClassFileAssembler from the sun.reflect package.
This class is a package local class:
class ClassFileAssembler implements sun.reflect.ClassFileConstants {...
So we can not use even its name ClassFileAssembler, we can not import it directly - it will lead to a compiler error.
However we can create a package named sun.reflect in our project and use the ClassFileAssembler name internally in this package - Java compiler will think that we are inside the ClassFileAssembler's package.
If so, why not to try to get a reference to a class object, i.e. ClassFileAssembler.class?
Class<ClassFileAssembler> classFileAssemblerClass = ClassFileAssembler.class;
Unexpectedly this code leads to a run-time error: java.lang.IllegalAccessError: tried to access class sun.reflect.ClassFileAssembler from class sun.reflect.Test.
However we still able to get the ClassFileAssembler class object:
Class<ClassFileAssembler> aClass = (Class<ClassFileAssembler>)Class.forName("sun.reflect.ClassFileAssembler");
It works fine and gives us a full class description.
So, the questions are:
1) What is the difference between techniques, how Class.forName0 retrieves reference to class object, and how .class does it?
2) Why do they have such different security checks?
3) What's the reason to protect .class reference in such way?
4) Do these techniques use different class loaders?
Class.forName don't care about whether a class is package local or not. It is when you attempt to use that class that access is checked. BTW if you do setAccessible(true) you can by pass these access restrictions.
The Reflection library allows you to do many things you cannot do in Java code. The Java has rules as to what you can and cannot do. e.g. you cannot set a final field outside a constructor or more than once. Note: the JVM doesn't have this restriction and at runtime you can use reflections to change it.
The reason this class is package local is to restrict access of the class to code outside this package. This doesn't mean you cannot access it if you really try, but it is less likely you will access it without serious thought being put into it. e.g. when I import classes in my IDE it often suggests classes from com.sun.* which are unlikely to be the right choice. (MY IDE can be set up to ignore these, but I often seem for find some new package I don't want)
The reason Reflections can do this is to support functionality such a Serialization. With Serialization you need to be able to serialize class outside the package of the Serialization library and obtain fields and reset them when deserializing. Reflections is also used by many Inversion of Control libraries though I suspect this is not what they had in mind when they design it.
If you check the javadoc of Class#forName, you will see that:
Note that this method does not check whether the requested class is accessible to its caller.
there is no difference. but you cannot access the static field .class of the package private (no modifier) class ClassFileAssembler.
everyone could access the Class instances, but the fields are protected.
in fact no one designed to protect .class reference this way, it's side effect of protecting other fields.
i dont think so.
As the title already says, I would like to know if it is somehow possible to give a class a different filename in Java with Eclipse ?
Edit: I only want to know if its possible with Eclipse. If you don't know the answer, please resist the urge to respond with condescending answers.
Edit2: It's hilarious what kind of responses I get here. All I wanted to know is if it is possible to have a class with a different filename (and I meant the public class) and nothing else. I thought this is the kind of forum to ask these questions, but the second response I got was already an insult. Is this some kind of taboo question or what is going on ?
Your filename should always match your class name, end of story. Although the JLS doesn't specifically state that it HAS to be done, they leave it up to the implementation of the compiler to make that decision. I'm pretty sure most (if not all) will not allow you to differ from that standard.
The JLS states:
When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
So while you may be able to rename the file itself in eclipse, or your filesystem - you will more than likely hit a compile error.
I don't know why you would like to do that but it is possible if you compile files from command line with help of symbolic links.
Let's say you have class YourClass saved in a file OtherName.java. If you create a symbolic link to that file like this:
UNIX system: (for sure doesn't work on Solaris - other system aren't verified)
ln -s OtherName.java YourClass.java
javac YourClass.java
WINDOWS system: (works on Windows Vista/2008+)
mklink YourClass.java OtherName.java
javac YourClass.java
the compiler finds the type and compilation works...
This solution is not verified on Unix systems, but works for sure on Windows Vista/2008+..
What does Eclipse have with the naming conventions or rules of Java Programming Language?
Eclipse is just an IDE, and if you are working with Java you have to obey its rules.
Lets's say you have X.java file. This means that you can have only one public / abstract / final class named X in this file. There is no limitation on the number of classes and their names and also their nesting relations with each other as far as no more than one class holds the filename as its class name. If a class takes the filename, then it should have one or more of these modifiers: public, static, final. That's the story.
No, the Java a public class and the file must have the same name.
If you try to give the class another name, the compiler will fail with
class YourClass is public, should be declared in a file named YourClass.java
But you can declare additional private classes in a file which contains a public class.
below are the situations where you can have different class name.
1.class is not public class and exists in a java file where atleast one public class is defined
class notpublic{
}
public class PublicClass {
}
2.Class is a InnerClass .
public class PublicClass {
class InnerClass{
}
}
I have file TestClass.java
package com.fido.android.sample.dsm.SoftPin.Core;
public class TestClass
{
public int mValue1;
public String mValue2;
}
Now in this file (TestClass.java) I want to declare one more class, but when I write for example:
public class SecondClass
{
// Class members goes here.
}
Compiler do not allow me to do that, if I remove public everything is Okay, but I can use SecondClass only in the TestClass.java, I can't write
SecondClass sc = new SecondClass();
out of TestClass.java class. Now I want to know if there is a way to do such thing, to have two classes in the same file and to use them from everywhere (not inner classes).
Question is: Why would you want to declare a second public class within the same Java class file? It is a rule in Java that each public class must be declared in a single class file - except for nested classes like Graham Borland pointed out.
Short answer: You can't.
That's how Java works.
You can only declare a single public class per file, with the class name the same as the file name.
You can use inner-classing as Graham suggested, or better yet, move the second class in a new file.
If you have SecondClass inside TestClass (i.e. nested inside the class definition), with public visibility, then you can refer to TestClass.SecondClass everywhere.
No, you can't, if the compiler chooses to enforce this rule from the Java Language Specification, section 7.6:
When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit.
So this is optional in that it's still "legal Java" to include more than one public top-level class in a single source file - but it's also valid for the compiler to reject it. In practice, I think every file-based Java compiler I've ever used enforces this rule.
Now you could try to find a different compiler if you really wanted, but there's a reason for this: Java programmers are used to finding the source code for a public top-level type (and usually any top-level type) in a source file with the same name.
To ask a return question provocatively: why do you want to make your source code hard to navigate?
You cannot.
What you can do is to have inner classes.
According to java conventions, A public class should be created in a separate file having same name as of class name.
So you cannot make two public classes in same file.
you can try either removing public from one class or making inner class.
Since public classes must have the same name as the source file , there can only one pulbic class inside a java file.
we can declare only one public file in a source file and file name must match the public class name
is there any reason to this restriction....
Well, it's not a compulsory restriction in Java. It's one that the Java Language Specification mentions as an option. From section 7.6 of the JLS:
When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
But basically it's there to encourage you to make your source easier to navigate. If you know the name of a public class, it's usually pretty easy to find the source code for it.
Yes, it's the specification of the Java language...
The reason is, that this is the convention. Also the classloader expects a class in a specific file. You can write your own classloader to avoid this restriction, but there is no good reason to do this. Everyone looking on your code will get confused. ;)
However, you can create "multiple" classes in one file by creating inner classes. I know, its not the same, but usually you should think about more important things than why there is only one class in one file.
It's there so that the compiler can find the source code of dependent classes.
#saravanan. I have executed some simple programs which show that just a single default class(ie a class with no access specifier) having the main method works well in java when u save the file name with the default class name.
To add on to the reason of naming the file with public class name, in a document I went through the details into this state that the JVM looks for the public class (since no restrictions and can be accessible from any where) and also looks for public static void main() in the public class .
This public class acts as the initial class from where the JVM instance for the java application( program) is begun.So when u provide more than one public class in a program the compiler itself stops you by throwing an error.
This is because later you can't confuse the JVM as to which class to be its initial class because only one public class with the public static void main(String args[]) is the initial class for JVM.
HOPE I have helped you in understanding JAVA programming naming better.
simply remember only that class would be public which has the main other files dont be public