Why doesn't the class containing main have to be public? - java

I declared the following class
class A { //not public
public static void main(String args[]) {
System.out.println("done");
}
When I compile and run it, it runs fine and prints the output "done". Same behavior even when I declare it as being in a "package a;"
However, if JVM spec mandates that main method should be public since "it can't see main otherwise", shouldn't it apply to the class as well?
If the JVM "can't see" A.main() when it is not declared public, how is it able to see the class A itself.
Is there any explanation for this other than "because the specification says so"?

The JVM has access to every class in the application all the time because one of its responsibilities is enforcing visibility rules. Therefore, one can draw the conclusion that it can ignore visibility rules if need be (e.g. when the user starts the application, the JVM has to find the entry point, which is main()).
In other words, the JVM is not a class accessing this function, so visibility doesn't apply. It is basically the overseer, managing the application from execution to termination.
For reference, see Execution.

When you declare a class private, you're not making it "invisible", and the same goes for your methods. Declaring a method private simply means it's not callable from outside your class. A static public method of a private class is publicly callable.

The reason the JVM can see a non-public class is because it controls visibility, meaning it sees everything and decides what can see/call/access what.
The use of public on a class is different than on a method, but the concept is the same.
On a method, the public keyword means the method can be used outside the class. An example would be:
class A {
public static void do() {
// Do something
}
}
class B {
public static void main(String[] args) {
A.do(); // This works because do() is public and static
}
}
The same concept applies to classes, but in a different way.
Using public on a class means that it can be used outside the current .java file (it will have its own .class file).
Here's an example:
//C.java
class C {
static void do() {
// Do something
}
public static void run() {
A.do(); // Works because A.do() is public and static
B.do(); // Does not work because B is not a public class
}
}
//A.java
public class A {
public static void main(String[] args) {
B.do(); // Works because B is in the same file
do(); // Duh...
}
public static void do() {
// Do something
}
}
class B {
static void do() {
// Do something
}
}

Related

In what order do local and anonymous classes compile in java?

Assume that I have two local classes with the same names, but they're defined in different methods. In what order will they compile and what names are they going to have?
class ExampleClass {
public void test() {
NestedClass.nestedTest2();
NestedClass.nestedTest();
}
private static class NestedClass {
private static int a;
public static void nestedTest() {
class Test1 {
void method1() {}
}
}
public static void nestedTest2() {
class Test1 {
void method2() {}
}
}
}
}
Using javac command I get these compiled files
ExampleClass$NestedClass$1Test1
ExampleClass$NestedClass$2Test1
There are other files, I just don't really thing it's necessary to list them all.
The question is, how come the first file (ending with $1Test1, which is defined in nestedTest() method ) get compiled earlier than the other one (defined in method nestedTest2)? What does the order depend on? As you see I also tried to call test methods in ExampleClass to change the order, but I didn't believe it would help and it actually doesn't.

Interface visibility restriction, but runs fine

When designing a fluid API, sometimes I want to use Interface return types so that the caller can easily follow the available methods or gets compiler errors if he does not (the Step Builder pattern is an example).
But when I want to use interfaces just to point to the next available method, like:
package packageone;
public class SomeClass implements CanPrint {
private SomeClass() {
}
public static CanPrint get() {
return new SomeClass();
}
#Override
public void print() {
System.out.println("Runs fine!");
}
}
public interface CanPrint {//Compile error: must be defined in own file
public void print();
}
However, firing up a quick test works fine (the following code prints "Runs fine!"):
package packagetwo;
import packageone.CanPrint;
import packageone.SomeClass;
public class Main {
public static void main(String[] args) {
CanPrint returnType = SomeClass.get();
returnType.print();
}
}
The compiler can be 'fooled' by wrapping the entire class:
package packageone;
public class Wrapper {
public static CanPrint get() {
return SomeClass.get();
}
public static class SomeClass implements CanPrint {
public static CanPrint get() {
return new SomeClass();
}
private SomeClass() {
}
#Override
public void print() {
System.out.println("Runs fine!");
}
}
public interface CanPrint {
public void print();
}
}
So currently when I want to keep the interfaces in the same place as the only code that is intended to use it (as the caller only needs the method), I wrap it in a wrapper class which only points to the same method in the inner class.
Why is this restriction in place? The other class can import the interface, use it, even implement their own version if they desire to do so. All of this seems to run without problems. Yet it does not compile.
Note: I've simplified my examples as much as I could, but because of this it might be less clear why one would choose this design.
Why is this restriction in place?
It makes it easier for the compiler and humans to find the source file containing a top-level class.
You can expose the interface by:
Placing the interface in a separate file, like ISomeClassCanPrint.
Or nesting the interface in the class that returns an instance. Your wrapper is close to this approach.
Here's another example of a nested interface:
public static class SomeClassFactory {
public interface CanPrint {
public void print();
}
public static CanPrint get() {
return new SomeClass();
}
public static class SomeClass implements CanPrint {
#Override
public void print() {
System.out.println("Runs fine!");
}
}
}
More detail
The restriction is covered by the Java Language Specification, section 7.6: Top level type declarations:
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).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a Java compiler to find a named class within a package. In practice, many programmers choose to put each class or interface type in its own compilation unit, whether or not it is public or is referred to by code in other compilation units.
So while you are allowed to declare multiple top-level classes in a single file, at most one can be exposed for access outside the file.
You can, however, expose as many nested classes as you want.

How do you transfer a variable defined in the main method of one class to another?

I have seen this done in many programs but I cant seem to follow the programming logic.
Lets say you have a simple class, ClassB. And in ClassB's main method you define an integer variable:
public class B {
public static void main(String[] args) {
int stuff = 333;
}
}
How can you transfer the variable to a different class, say ClassA, to be used.
public class A {
public static void main(String[] args) {
System.out.println(stuff);
}
}
Can someone please explain this to me in simple terms. I've been trying to learn this for 2 hours and cant wrap my head around it.
public static void main(String[] args) is meant to be used as a starting point for a Java program. Probably it's better to rename one of your methods to something else.
The problem you are seeing, is that the scope of the variable int stuff is limited to the main() method of class B, because it is declared within the body of the main() method. In order to make it visible, you need to declare it as a public field (which can be static in your case).
I propose you change your program like follows:
public class A {
public static int stuff;
public static void initStaticMembers() {
stuff = 333;
}
}
public class B {
public static void main(String[] args) {
A.initStaticMembers();
System.out.println(A.stuff);
}
}
I renamed the main() method of A to initStaticMembers() and dropped the method parameters, since they are not needed in our case. In order to use the field A.stuff in B, the method A.initStaticMembers() needs to be called first.
Of course there are ways to improve this program, but I think you should learn Java one step at a time.
You shouldn't have 2 main methods. Only one class should (typically):
ClassA.java
public class A {
public static void main(String[] args) {
ClassB b = new ClassB();
System.out.println(b.stuff);
}
}
ClassB.java
public class B {
public int stuff = 333; // member variable
}
You instantiate the second class in the first one, then you're granted access to its public member variables.

Creating a class with all of my functions in java

How can I create a class with all my functions in java?
when I create functions (methods) in a class, I can't seem to use them in other class.
I would like to create a single class for all the impotent functions and call them from there
public class all_function(){
public int func1(...)
public int func2(...)
.
.
.
}
and than for all other classes, using those functions
public class main_app
function.func1(...)
when trying to do so I get an error indicating that the function is not declared etc.
thanks
#Quincunx's answer in the comments is correct, but writing whole programs like this violates all sorts of OO principles, and it's not a good idea for readability, maintainability, etc. You probably want to go back and read some basic Java tutorials.
For example, to use a method outside of the class that declares it, you need to create an instance of that object:
public class Foo {
public void doSomething() {
System.out.println("I did something!");
}
}
public class Bar {
public static void main(String[] args) {
Foo foo = new Foo();
foo.doSomething();
}
}
If you have a method that's not specific to the class that declares it (i.e., a utility class), though, then by all means declare it static:
public class Foo {
public static void doSomething() {
System.out.println("I did something!");
}
}
public class Bar {
public static void main(String[] args) {
Foo.doSomething();
}
}

Main method in a static inner class.?

I've learnt that the only public class in a Java file must also have the main method. However, below you can see the main method inside an inner class instead?
What is the rule with regard to the main method definition in a source file?
public class TestBed {
public TestBed() {
System.out.println("Test bed c'tor");
}
#SuppressWarnings("unused")
private static class Tester {
public static void main(String[] args) {
TestBed tb = new TestBed();
tb.f();
}
}
void f() {
System.out.println("TestBed::f()");
}
}
If you want to start a class with java (the Java launcher: java test.MyClass) then this class must have a main method with the well known signature.
You can have a main method with the same signature anywhere you want. But don't expect that the launcher will find it.
P.S. The name of the language is Java, not JAVA.
There is a minor detail:
You may do this:
package test;
public class Test {
/**
* #param args the command line arguments
*/
static public class A {
public static void main(String[] args) {
System.err.println("hi");
}
}
}
java test.Test$A
but this is non standard ...
Any class that can have a static method can have a public static void main(String[] args).
This includes:
top-level classes (whether public or not), e.g.
public class Foo {
public static void main(String[] args) {
System.out.println("Hello");
}
}
and inner static classes (whether public or not) (like your example).
It does not include:
anonymous classes
inner non-static classes
So both of these are illegal:
public class Foo {
private Object bar = new Object() {
public static void main(String[] args) {
System.out.println("Hello");
}
};
}
public class Foo {
private class Bar {
public static void main(String[] args) {
System.out.println("Hello");
}
};
}
Every Java application must have a main method. It’s the starting point for the execution of the code in the application. Its method signature is:
public static void main(String[] args)
A static inner class is a class that is defined inside of a different class's definition and marked as being static.
For example, if the outer class is named TestBed, then an inner class of TestBed, which is named Tester, would be compiled into TestBed$Tester.class. The separation of .class files means that you can keep the supplemental, nested code tightly coupled to the primary, outer class.
They are in the same source file, and the inner class is actually inside the outer class. All that and you don't have to pay any sort of deployment or run time cost.
By using static inner classes, you can add additional support functionality to your systems for capabilities such as testing, while incurring no penalties in normal, production deployment.
To execute the main() method of that TestBed.Tester class,
% java TestBed$Tester
This is interesting as the code will compile and run in Eclipse, but will just compile from using commmand line. When you run from eclipse it will find the static main method from within the inner class and run it.
But when running java TestBed from the command line you will get error - Exception in thread "main" java.lang.NoSuchMethodError: main which is a valid error as you have not defined your main method in main class.
Why would you want to define your main method in an inner class? Your main method should be defined in public class, this is not a rule but common practice.
In below code I've moved the main method into outer class which works both in Eclipse & command line :
public class TestBed {
public TestBed() {
System.out.println("Test bed c'tor");
}
#SuppressWarnings("unused")
private static class Tester {
}
public static void main(String[] args) {
TestBed tb = new TestBed();
tb.f();
}
void f() {
System.out.println("TestBed::f()");
}
}

Categories

Resources