I have a java file containing more than one class, out of which one is public. If main method is inside a non-public class. I can't run that java file. Why is that? and there is no compilation error as well. If so, how can I use that main method?
Actually you can execute the main method in a non-public class. if you put this class
class A {
public static void main(String... args) {
System.out.println("This is not a public class!");
}
}
in a file named NonPubClass.java. You can compile this file using javac command but you will not get a NonPubClass.class, you will get a A.class instead. Use java a to invoke that class and you will see the printed string --- This is not a public class!
Have a look at this code:
Super.java
public class Super{ }
class Sub{
public static void main(String[] s){
System.out.println("Hello");
}
}
In order to print Hello you can compile and run the program as:
How this works?
The compiler generates separate .class file for every class in your program. So, instead of calling the main() of non-public class from the public class's main() you can print the output as shown above.
Note: As the convention says, you must put a public class in separate file <class_name>.java. And do not put more than one class in a single file (except if they are inner class) because if you would like to import them or use them with other classes then it will cause problem.
there is something i would like to add although everybody here believes that a public is necessary for the main in a class and that it won't work without main
you can have as many mains in a class as you desire, and you can have them without a public access modifier.
but be careful, only that class which is named after the file can be public
what i mean is if you name your file a.java , then only the class with name a can be public, none other can have this facility
here is a code to show this :
as you can see the name of the file is helping.java
//:initialization/helping.java
class b{
public static void main(){
System.out.println("hello its b");
}
}
class helping {
static void f(float i, Character... c) {
System.out.println("first");
}
static void f(char a, Character... args) {
System.out.println("second");
}
public static void main(String[] args) {
f(1,'a');
f('a','b');
c.main();
}
}
class c{
public static void main(){
System.out.println("hello its b");
}
}
//:~
/*
* output:
* first
* second
* hello its b
* */
Simple Answer. You can't. You need to have main method in a public class and its signature should be public static void main(String... args)
there is no compilation error
Why there would be? You are doing nothing wrong as far as compilation rules are concerned.
Only thing is that your non-public-class-main-method won't work as an entry point of your code.
It is a compile-time error if a top level type declaration contains any one of the following access modifiers: protected, private, or static.This link may be helpful.
It's not a compile time error as u mentioned that top level type declaration shouldn't be protected, static or private.
If u go through the link http://docs.oracle.com/javase/specs/jls/se7/html/jls-7.html#jls-7.6 well that u have shared ,then it's quite clear there that a top-level type declaration refers to only "top level Class and Interface type declarations" and these should not be protected, static or private at top level declarations, but we can use protected, static or private for any methods or variable declaration inside them.
With respect to above code, there is nothing wrong in declaration, and the code will compile and run successfully as all outer top level class are default and there is no violation.
The answer to the question asked at top is exactly as mentioned by few experts at top, that
"for sure we can have a file with main method inside non-public class and it will compile as well as run successfully, but make sure that at the time of running the program we have to pass the class name of "main method" to the java interpreter instead of the class which is public."
If we have 2 classes A(public) and B(non-public containing main method) , then the file will compile with "javac A.java" but while running the code we need to pass the command as "java B" .
You can certainly override main method and it does not violate any compiler rules and hence you will not have any compiler errors.
You check that inspite of the fact that you have more than one class a file that is declared as public is the name of the file you are trying to execute.
This is a convention that the file should be named after the same class which is public in that code.
Hence when you try to execute that class it does not have a main method from which it starts execution.So if you want to execute the main method in the non public class the only way to this is call that main from a main method of the public class.
Related
I have 2 classes in a single Java source file, and the name of the source file is the same as the public class. When I run the source file, I get the following error:
package inheritance;
class clsnae {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("first");
}
}
public class clsname {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("second");
}
}
May I know why my compiler or JRE can't find my other file (non-public file)?
If I remove the public keyword, it just prints "first" and not "second", but after adding the public keyword to the class name, why does it still try to run the first class instead of running the second class?
Your code is fine. There are two main methods and you can run any of them at a time.
For the first time eclipse would ask you which main method to run.
If you want to change later, you can modify your run configurations and choose your main class.
Goto Run configurations:
and then choose the main class:
Here's the sample run:
This has more to do with Java Specification.
The rule says if you are declaring a class as public the name of the file in which the class resides MUST have the same name.
However, The same rule doesn't apply if you don't specify the public modifier while defining your class. so you can save the file using any classname.
In your case Rule 1 violates.
For more details: Refer to the following answer:
Why are filenames in Java the same as the public class name?
Since there are two main methods the Eclipse will prompt you with the classes having the main method to execute. in the current class.
Regarding the example code below, although the Test() constructor inside the class Test is public, the class Test itself isn't public, and so the Test() constructor can't be called from outside its own package.
Does that make the public keyword redundant? If so, I wonder why javac doesn't issue a warning about the redundant use of public, when used inside a class whose access is implicitly declared as default ("package private")?
Test.java, package test -
package test;
class Test {
public Test() {}
}
Main.java, package main -
package main;
class Main {
public static void main(String[] args) {
new test.Test(); // Expected error
}
}
EDIT:
Just to be clear: it's when I compile Test.java, that I get no warning.
The user comments made to my original post have helped me solve this problem: I now realise that an IDE will give me the information that I was after, and that just using javac on its own will not. Thanks.
I have the following code as part of an assignment
class Base {
public static void main(String[] args){
System.out.println("Hello World");
}
}
public class Factorial extends Base{
}
My task is run the code and then explain the output.The name of the file is Factorial.java. The code runs without problem and Hello World is printed which to me is surprising. Before typing the code, I was thinking that it wont compile because the parent class, which is being extended should be in another file but now I am not so sure. Would appreciate soome clarification.
Java allows you to define multiple classes within a single .java file with the condition that you can have at most one public class and if you do then the name of that public class must match the name of the .java file. In your case, the class declared public is Factorial and hence your file name has to be Factorial.java.
The inheritance is working as usual here and the public static void main() is inherited by Factorial which is why you see your output on executing java Factorial.
You can have more than one class in the same file, but only one public , as Base isn't a public class, but it's not a recommended practice.
I am little bit confused of classes names.This is my problem ...i tried to give same class name in two different files and in the same package with default access modifier and even i tried with interfaces even then it is not showing any errors.i want to how they are actually accessed.
i dont understand how these classes are interface will be used...whether a class in a file checks for presence of class or interface (if it want to use ) first in local file and then check in outside with in the package or any thing else.i am not getting any clarity.If any one understand the trouble what i am facing,i hope will help me.....
// This is InterfaceTest
package Practice;
interface t{
public void h();
public void h1();
}
abstract class InterfaceTest implements t{
public void h(){
}
public void h1(){
}
public abstract void t();
}
//This is other file InterfaceTest1
package Practice;
interface t{
public void h();
public void h2();
}
public class InterfaceTest1 {
}
//This is TestStack file
package Practice;
public class TestStack {
Test t=new Test();
public static void main(String[] args){
TestStack t1=new TestStack();
InterfaceTest it=new InterfaceTest();
}
}
interface t{
public void h3();
}
class Test implements t{
public void h3(){
}
public void h1(){
}
public void h2(){
}
}
class InterfaceTest{
}
These three files used in the same package but i am not getting any errors in name collision
It isn't very clear what you are saying but I'll take a stab at it - leave a comment if I'm not understanding you.
In Java, a class is identified by its fully qualified name. The fully qualified name is .classname.
For example, if a class is in the com.foo.bar package and is named MyClass, the fully qualified name would be com.foo.bar.MyClass. If you have more than one class with the same fully qualified name, you will have a collision and the JVM won't know which class to use. In order to use a class in a different package, you have to import it. You would import the above class with a statement at the top of your java file lie import com.foo.bar.MyClass or, if you wanted to import the entire package, you would use import com.foo.bar.* although that is considered bad practice. Interfaces behave in the same manner. Classes in the same package as a given class do not need to be imported. So, another class in the com.foo.bar package that wishes to use MyClass, would not need to import it.
Does that help you at all? If you can clarify your question, I can try to help you more.
Edit To address your clarification, you can only have one top level, public class per java file. If you wish to define additional public interfaces or classes in a file, they must be nested inside the top-level class. If you use a class and don't fully qualify it, the compiler will first look for a nested class with that name and then look for a class in the same package with that name. If it still can't find it, and you haven't imported it, then it will fail with a class resolution error.
Edit 2 Ah I think I understand. Are you attempting to use those classes in a different class? The compiler won't complain until it attempts to resolve the class that has a name collision. If that class isn't referenced anywhere, the compiler won't care. If you have two MyClass classes, but neither is used anywhere, then the compiler won't bother trying to resolve the class and won't notice the collision. Yes, inside of MyClass if you attempt to reference MyClass it's going to assume that you are referring to the class you are in.
Edit 3 One last try, if you have MyClass and then have another class nested inside it, MyClass1, the fully qualified name for MyClass1 is com.foo.bar.MyClass$MyClass1 because it is nested as part of MyClass
Interface and class names within a package have to be unique:
package foo;
public interface Bar
{
void print();
}
class Bat implements Bar
{
public void print() { System.out.println("Hi there"); }
}
You can have duplicate interface or class names if the packages are different. Fully-resolved class names must be unique.
package other;
public class Bat
{
public void doSomething()
{
System.out.println("And now for something completely different");
}
}
UPDATE:
The example code you present is preposterous. Bad naming conventions aside, you have interface t defined in two separate files. What made you think that you needed to copy and paste it into the second file once you had the first one? Remove interface t from the file containing the definition for InterfaceTest1.
All these are in the same package Practice. What makes you continue to define interface t again and again and again? You also have it in that TestStack definition. Please, think of some unique names if the definitions are indeed unique and your problem goes away.
In Java, you can define multiple top level classes in a single file, providing that at most one of these is public (see JLS ยง7.6). See below for example.
Is there a tidy name for this technique (analogous to inner, nested, anonymous)?
The JLS says the system may enforce the restriction that these secondary classes can't be referred to by code in other compilation units of the package, e.g., they can't be treated as package-private. Is that really something that changes between Java implementations?
e.g., PublicClass.java:
package com.example.multiple;
public class PublicClass {
PrivateImpl impl = new PrivateImpl();
}
class PrivateImpl {
int implementationData;
}
Javac doesn't actively prohibit this, but it does have a limitation that pretty much means that you'd never want to refer to a top-level class from another file unless it has the same name as the file it's in.
Suppose you have two files, Foo.java and Bar.java.
Foo.java contains:
public class Foo
Bar.java contains:
public class Bar
class Baz
Let's also say that all of the classes are in the same package (and the files are in the same directory).
What happens if Foo refers to Baz but not Bar and we try to compile Foo.java? The compilation fails with an error like this:
Foo.java:2: cannot find symbol
symbol : class Baz
location: class Foo
private Baz baz;
^
1 error
This makes sense if you think about it. If Foo refers to Baz, but there is no Baz.java (or Baz.class), how can javac know what source file to look in?
If you instead tell javac to compile Foo.java and Bar.java at the same time, or if you had previously compiled Bar.java (leaving the Baz.class where javac can find it), or even if Foo happens to refer to Bar in addition to Baz, then this error goes away. This makes your build process feel very unreliable and flaky, however.
Because the actual limitation, which is more like "don't refer to a top-level class from another file unless it either has the same name as the file it's in or you're also referring to another class that's named the same thing as that file that's also in that file" is kind of hard to follow, people usually go with the much more straightforward (though stricter) convention of just putting one top-level class in each file. This is also better if you ever change your mind about whether a class should be public or not.
Newer versions of javac can also produce a warning in this situation with -Xlint:all:
auxiliary class Baz in ./Bar.java should not be accessed from outside its own source file
Sometimes there really is a good reason why everybody does something in a particular way.
My suggested name for this technique (including multiple top-level classes in a single source file) would be "mess". Seriously, I don't think it's a good idea - I'd use a nested type in this situation instead. Then it's still easy to predict which source file it's in. I don't believe there's an official term for this approach though.
As for whether this actually changes between implementations - I highly doubt it, but if you avoid doing it in the first place, you'll never need to care :)
I believe you simply call PrivateImpl what it is: a non-public top-level class. You can also declare non-public top-level interfaces as well.
e.g., elsewhere on SO: Non-public top-level class vs static nested class
As for changes in behavior between versions, there was this discussion about something that "worked perfectly" in 1.2.2. but stopped working in 1.4 in sun's forum: Java Compiler - unable to declare a non public top level classes in a file.
You can have as many classes as you wish like this
public class Fun {
Fun() {
System.out.println("Fun constructor");
}
void fun() {
System.out.println("Fun mathod");
}
public static void main(String[] args) {
Fun fu = new Fun();
fu.fun();
Fen fe = new Fen();
fe.fen();
Fin fi = new Fin();
fi.fin();
Fon fo = new Fon();
fo.fon();
Fan fa = new Fan();
fa.fan();
fa.run();
}
}
class Fen {
Fen() {
System.out.println("fen construuctor");
}
void fen() {
System.out.println("Fen method");
}
}
class Fin {
void fin() {
System.out.println("Fin method");
}
}
class Fon {
void fon() {
System.out.println("Fon method");
}
}
class Fan {
void fan() {
System.out.println("Fan method");
}
public void run() {
System.out.println("run");
}
}
Just FYI, if you are using Java 11+, there is an exception to this rule: if you run your java file directly (without compilation). In this mode, there is no restriction on a single public class per file. However, the class with the main method must be the first one in the file.
1.Is there a tidy name for this technique (analogous to inner, nested, anonymous)?
Multi-class single-file demo.
2.The JLS says the system may enforce the restriction that these secondary classes can't be referred to by code in other compilation units of the package, e.g., they can't be treated as package-private. Is that really something that changes between Java implementations?
I'm not aware of any which don't have that restriction - all the file based compilers won't allow you to refer to source code classes in files which are not named the same as the class name. ( if you compile a multi-class file, and put the classes on the class path, then any compiler will find them )
Yes you can, with public static members on an outer public class, like so:
public class Foo {
public static class FooChild extends Z {
String foo;
}
public static class ZeeChild extends Z {
}
}
and another file that references the above:
public class Bar {
public static void main(String[] args){
Foo.FooChild f = new Foo.FooChild();
System.out.println(f);
}
}
put them in the same folder. Compile with:
javac folder/*.java
and run with:
java -cp folder Bar
According to Effective Java 2nd edition (Item 13):
"If a package-private top-level class (or interface) is used by only
one class, consider making the top-level class a private nested class
of the sole class that uses it (Item 22). This reduces its
accessibility from all the classes in its package to the one class
that uses it. But it is far more important to reduce the accessibility
of a gratuitously public class than a package-private top-level class:
... "
The nested class may be static or non-static based on whether the member class needs access to the enclosing instance (Item 22).
No. You can't. But it is very possible in Scala:
class Foo {val bar = "a"}
class Bar {val foo = "b"}