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.
Related
For some reason I keep getting an error saying
The public type Dog must be defined in its own file
when I try to compile. Does anyone here know how I can fix it?. Anyone know what I did wrong? I tried looking at some other answers but it said some weird mumbo jumbo about importing something.
If your file name and public class name differs then you get this type of error.
From the error The public type Dog must be defined in its own file I am pretty sure that your file name is not Dog.java
Each Java compilation unit (a .java file in all common systems) must contain exactly one top-level type (class, enum, or interface) whose simple name exactly matches the name of the file without the .java extension.
It doesn't matter what the access modifier on the class is (public or default), and public nested classes can be placed inside the top-level type, but the single top-level type must match the file name.
(This requirement is technically optional at the discretion of the compiler implementer, but I don't know of any compilers that don't enforce it, and code should always assume the compiler will.)
Move the code for the Dog class to a file called Dog.java
All top-level classes e.g. the public Dog class you want to call from another class must exist in their own specially named files.
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
I've been using Eclipse as my IDE. I also use it to export my application into a JAR file. When I look at my classes in the JAR file, a few of my classes contain the name of that class, a dollar sign, then a number. For example:
Find$1.class
Find$2.class
Find$3.class
Find.class
I've noticed it does this on bigger classes. Is this because the classes get so big, it compiles it into multiple classes? I've googled and looked on multiple forums, and search the Java documentation but have not found anything even related to it. Could someone explain?
Inner classes, if any present in your class, will be compiled and the class file will be ClassName$InnerClassName. In case of Anonymous inner classes, it will appear as numbers. Size of the Class (Java Code) doesn't lead to generation of multiple classes.
E.g. given this piece of code:
public class TestInnerOuterClass {
class TestInnerChild{
}
Serializable annoymousTest = new Serializable() {
};
}
Classes which will be generated will be:
TestInnerOuterClass.class
TestInnerOuterClass$TestInnerChild.class
TestInnerOuterCasss$1.class
Update:
Using anonymous class is not considered a bad practice ,it just depends on the usage.
Check this discussion on SO
This is because you have anonymous classes within this larger class. They get compiled using this naming convention.
See The Anonymous Class Conundrum
In addition to the above cases presented by #mprabhat, the other cases could be:
if you class contain a enum variable a separate class would be generated for that too. The name of the .class generated would be ClassName$Name_of_enum.
If your class X is inheriting i.e. extending another class Y, then there would be a .class generated with the name ClassName$1.class or ClassName$1$1.class
If your class X is implementing an interface Y, then there would be a .class generated with the name ClassName$1.class or ClassName$1$1.class.
These cases are derivations of my inspection on .class files in jar.
To answer your comment about are anonymous classes bad. They are most definately not.
Consider this to assign an action listener to a JButton:
JButton button = new JButton(...);
button.addActionListener(new ActionListener() { ... });
or this to do a case insensitive sort by the "name" property
Collections.sort( array, new Comparator<Foo>() {
public int compare(Foo f1, Foo f2) {
return f1.getName().toLowerCase().compareTo(f2.getName().toLowerCase());
}
});
You'll also see a lot of Runnable and Callable done as anonymous classes.
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
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