Two public classes in one file java - java

Ok, this might be kiddies question in java. We can't define two public classes in one file. But, in one of the examples from the book SCJP study guide, this example was mentioned:
public abstract class A{
public abstract void show(String data);
}
public class B extends A{
public void show(String data){
System.out.println("The string data is "+data);
}
public static void main(String [] args){
B b = new B();
b.show("Some sample string data");
}
}
When I copy pasted this into netbeans immediately compile error was thrown, that public class A should me mentioned in separate file. Is that example from SCJP styudy guide really wrong? Also in some of the mock test I found many questions having such pattern but in none of the options was a compiler error was mentioned. Getting worried here

yes, 2 top level public classes are not allowed in one file

Well, if one is being so picky: you can have multiple classes defined with a public modifier in the same file, that is, using the static nested(inner) class.
like this:
File -> Test.java
public class Test {
public static class SomeNestedClass {
}
}

Yes you can have two classes in the same file. You can have them by removing the public access modifier from both the class name, like shown below,
abstract class A{
public abstract void show(String data);
}
class B extends A{
public void show(String data){
System.out.println("The string data is "+data);
}
public static void main(String [] args){
B b = new B();
b.show("Some sample string data");
}
}

you can make 2 public classes in one file , inside a class that contains them .
it's also recommended to add "static" for them , if you do not need any reference to the container class .

You can put two public classes in one file, for example in the file Circle.java:
public class Test {
public static void main(String args[]) {
double cir = Circle.findCircumference(7.5);
System.out.print("Circumference of circle=" + cir);
}
}
public class Circle {
public static double findCircumference(double radius) {
return 2 * Math.PI * radius;
}
}
If you then run javac Circle.java, you will get an error:
Circle.java:1: error: class Test is public, should be declared in a file named Test.java
public class Test {
^
1 error
But if you run it with java Circle.java, then it will work.
Why? Probably because the java command, since java 11 (see here), can run also single source-file programs.

Imagine you could place two public classes in one file, then think about the work of the compiler: it has to build a .class file from your .java file that represents exactly one class (otherwise the .class ending wouldn't make any sense).
The way the JAVA Compiler works it will simply create a .class file with the name of your file and will search for the class with the name of the file in your given file – so it depends on your file name which class will be correctly compiled and which will not.
Long story short: no, you can't put two public classes in one file because the compiler wouldn't be able to handle that correctly.
(Edit: it of course is possible to define new classes INSIDE the one public class that has the same name as your file.)

Related

How to use multiple classes in java in one file?

I want to know how to use multiple classes in one file in java. I typed this code but it is showing compilation errors.
class test {
int a, b, c;
void getdata(int x, int y) {
a = x;
b = y;
}
void add() {
c = a + b;
System.out.println("Addition = " + c);
}
}
public class P8 {
public static void main(String[] args) {
test obj = new test();
test.getdata(200, 100);
test.add();
}
}
You can only have one public top-level class per file. So, remove the public from all but one (or all) of the classes.
However, there are some surprising problems that can happen if you have multiple classes in a file. Basically, you can get into trouble by (accidentally or otherwise) defining multiple classes with the same name in the same package.
If you're just a beginner, it might be hard to imagine what I'm going on about. The simple rule to avoid the problems is: one class per file, and call the file the same thing as the class it declares.
The compilation errors in the classes you showed us have nothing to do with having two classes in the file.
public static void main(String[] args) {
test obj = new test();
test.getdata(200, 100); // error here
test.add(); // error here
}
When I compile your code using javac the error messages are:
$ javac P8.java
P8.java:21: error: non-static method getdata(int,int) cannot be referenced from a static context
test.getdata(200, 100);
^
P8.java:22: error: non-static method add() cannot be referenced from a static context
test.add();
^
2 errors
The problem is that test is a class name, not the name of a variable. As a result you are trying to invoke instance methods as if they were static methods.
But to my mind, this is a classic "I've shot myself in the foot Mum" moment.
You have broken one of the most widely observed rules of Java style.
Java class names should always start with an uppercase letter.
You have named your class test rather than Test. So when you wrote
test.getdata(200, 100);
test looks like a variable name, and that looks like a call of an instance method. But it isn't.
My bet is that this is part of what caused you to misconstrue the error message as being related (somehow) to having two classes in a file.
There is another stylistic howler in you code. You have called a method getdata but it actually behaves as a (sort of) setter for the Test class. If your code wasn't so small that it fits on a single page, that would be really misleading.
And finally, I agree with people who advise you not to put multiple top level classes into a single source file. It is legal code, but unnecessary. And style guides typically recommend against doing it.
i hope it will help you....
i just changed test.getdata() to obj.getdata()
and test.add() to obj.add() ..... check it out..
class test {
int a,b,c;
void getdata(int x, int y) {
a=x;
b=y;
}
void add() {
c=a+b;
System.out.println("Addition = "+c);
}
}
public class P8 {
public static void main(String[] args) {
test obj = new test();
obj.getdata(200,100);
obj.add();
}
}
you can not call test.getdata()..
and test.add()... as its not static methods
You can use at most one public class per one java file (COMPILATION UNIT) and unlimited number of separate package-private classes.
Compilation unit must named as public class is.
You also can have in your public class the unlimited number of inner classes and static nested classes.
Inner classes have an intenal pointer to the enclosing class so they have access to its members as well as local vars. They can be anonymuous.
Static nested classes is just like regular pubic class but is defined within enclosing class
Here's a very basic example of how to nest classes within classes. For this example, let's say that my file is named Test.java
public class Test {
public Test() {
}
class Person {
public Person() {
}
}
}
You should really take a look at how constructors work, because that may be one of your problems. Can't tell what else without more info, unfortunately.
{
// you have to call the method by the object which you are created. then it will run without error.
Test obj = new Test();
obj.getdata(20, 10);
obj.add();`
}
You have to nest your classes in each other, although it is not recommended.
public class P8 {//Currently inside P8 class
class test {//Declaring while inside P8
private int a, b, c;//Private vars in a nested class
void getdata(int x, int y) {
a = x;
b = y;
}
void add() {
c = a + b;
System.out.println("Addition = " + c);
}
}
public static void main(String[] args) {//Running the main for P8 class
test obj = new test();
test.getdata(200, 100);
test.add();
}
}
One of the reasons nesting classes is a bad idea is it strips the class of its privacy. The 'private' tag in java take whatever variable is tagged with it, and will only let that class access it, but if the class is inside another, both classes can freely access those private variables.

Accessing multiple classes from another java file

I am stuck on an assignment question where the task is only to break-down a single java file containing multiple classes into multiple java files and then import these java files so that the original project still works.(4 classes in total, moving 3 of them to separate files)
I create a new Project and move one class to that new project. Then import it to my original file and set the necessary functions to public and it works.
For the other two classes, I have to make a new Project with a completely different name(say Five) and paste the clases Three and Four into this Project. And then import these two classes into the original file.
I do that and it says the classes Three and Four should be public. That however is not possible since the class Five is already public. How do I access these two classes from the original file?
Project One: (This is the one im trying to run)
package one;
import two.Two;
import five.Five;
public class One {
public static void main(String[] args) {
...
}
)
class Customer{
...//this class accesses attributes and methods of classes
//Two, Three and Four. The error occurs for methods from classes Three and Four
}
Project Two
package two;
public class Two {
public static void main(String[] args) {
...
}
)
Project Five
package five;
public class Five {
public static void main(String[] args) {
...
}
}
class Three{
...
}
class Four{
...
}
Take a look at this question (and answer): Can a java file have more than one class?
You can only have one public class per file. If you don't want Three and Four as inner static classes in Five, you must put them in separate files Three.java and Four.java.
Also, package can be equivalent to a folder, so if your classes are in the same folder (part of one module/logic unit) they can all be in the same package, say main.
Thus your package main will contain all classes in a Java file each (it's also the good practice, unless a class is logically a sub-unit of another class). Also note that no imports are required in classes in the same package. They don't even have to be public.
as in above answer in one .java file has only one public class we cant make other class public so, other classes cannot be access by the classes of different packages because those classes are default and their visibility only in it's package. other package cannot access those classes.
But if you really want to do below example is one of the way to do that.
package pack1;
public class A {
public void sum(int a, int b){
System.out.println("Addition of a and b ="+(a+b));}
public static class Sub
{
public void subtraction(int a, int b)
{
System.out.println("subtraction a-b ="+(a-b));
}
}
}
// below main class is written and in that main class we are accessing the above classes of pack1
package mypack;
import pack1.*;
public class B {
public static void main(String[] args) {
A o1=new A();
int a=50,b=20;
o1.sum(a,b);
A.Sub o2=new A.Sub();
o2.subtraction(a,b);
}
}

Inner classes with the same name as an outer class?

Constraints:
I have a maven source code generator that I wrote that is creating POJO classes
from some data files that have nested namespaces. I want each namespace to
be nested as an inner class. In some cases out of my control I end up
with inner classes that are the same simple name as the outermost
class.
All the classes must be public scope as this is for a type safe
wrapper over something like a properties file, but hierarchical..
I can't change the names otherwise I am changing the names meaning and the namespace
that is enclosing data.
Given than I have the following code:
public class A
{
public class B
{
public class A
{
}
}
}
Inner classes should append the name of the outer class to form a unique namespace such as A$B$A.class, I haven't found a valid reason for this not to compile.
Is there any trick to get this to compile?
No. From the JLS section on class declarations:
It is a compile-time error if a class has the same simple name as any of its enclosing classes or interfaces.
Note: I somehow managed to miss this on my first pass through looking for an explicit rule. Check the edit history if you want the tortuous way I got here.
You asked: Is there any trick to get this to compile?.
The answer is: Well, maybe....
Create a class like the following:
public class A
{
public class B
{
public class X
{
}
}
}
And a class where this class is going to be used
public class AUse
{
public static void main(String[] args)
{
A.B.X aba = new A().new B().new X();
System.out.println("Created "+aba+" of class "+aba.getClass());
}
}
Then, download the Apache Byte Code Engineering Library (BCEL), and create and run the following class:
import java.io.FileOutputStream;
import org.apache.bcel.Repository;
import org.apache.bcel.util.BCELifier;
public class CreateCreators
{
public static void main(String[] args) throws Exception
{
new BCELifier(
Repository.lookupClass("A"),
new FileOutputStream("ACreator.java")).start();
new BCELifier(
Repository.lookupClass("A$B"),
new FileOutputStream("A$BCreator.java")).start();
new BCELifier(
Repository.lookupClass("A$B$X"),
new FileOutputStream("A$B$XCreator.java")).start();
new BCELifier(
Repository.lookupClass("AUse"),
new FileOutputStream("AUseCreator.java")).start();
}
}
This uses the BCELifier class from the BCEL. This is a class that takes a .class file, and creates a .java file that can be compiled to a .class file, that, when it is executed, creates the .class file that it was originally fed with. (Side note: I love this library).
So the A$B$XCreator.java file that is created there contains the BCEL code that is necessary to create the A$B$X.class file. This consists of statements like the generation of the constant pool and the instructions:
...
_cg = new ClassGen("A$B$X", "java.lang.Object", "A.java",
ACC_PUBLIC | ACC_SUPER, new String[] { });
...
il.append(_factory.createFieldAccess("A$B$X", "this$1",
new ObjectType("A$B"), Constants.PUTFIELD));
Similarly, the AUseCreator.java contains the BCEL code that creates the AUse.class. For example, the instruction of the constructor invocation of `A$B$X':
...
il.append(_factory.createInvoke("A$B$X", "<init>", Type.VOID,
new Type[] { new ObjectType("A$B") }, Constants.INVOKESPECIAL));
Now you can simply replace the String occurrences of "A$B$X" with "A$B$A" in the A$B$XCreator.java and AUseCreator.java, and then compile and run these classes.
The result will be a A$B$A.class file, and a AUse.class file that uses the A$B$A.class. Executing the AUse will print
Created A$B$A#15f5897 of class class A$B$A
I'm not sure whether this is considered as a "trick", or whether it still can be called "compiling" at all, but there is a way, at least. The key point is here, of course, that the fact that it did not compile is solely due to a limitation of the language, but there is no reason why this should not be representable in form of class files, regardless of how they are created.
You can't get it to compile, but more importantly, why would you need to?
What's wrong with:
public class A
{
public class B
{
public class InnerA
{
}
}
}
This seems like a design problem that you need to fix. If you can't rename it, consider anonymous inner classes. Or take some of those classes outside. Or just don't even use them.
It's a bit of a hack, but this compiles at my machine:
class A
{
public class B
{
public class Α
{
}
}
}
Try it. Literally: copy-past this thing ;)
SPOILER:
The name of the inner class is a capital letter alpha of the Greek alphabet. It's a Unicode character.
Depending on what you're after, the following might work for you:
public class A {
class B extends C {
}
public static void main(String[] args) {
new A().new B().new A();
}
}
class C {
class A {
{
System.out.println(getClass());
}
}
}

When compiling codes with inner class, why the strange output file is created?

I compiled this code and then, TestInner$1.class emerged.
I know ~~~$1.class indicates that file has "anonymous class."
But I don't understand the reason why this class file made. I want to know the reason.
Here is the code.
public class TestInner {
private static class Inner { }
public static void main(String[] args){
new Inner();
}
}
I tried another version removed "private" identifier, like the following.
public class TestInner {
static class Inner { }
public static void main(String[] args){
new Inner();
}
}
I'd imagined that this code also would make TestInner$1.class file.
However it didn't create the file.
In addition, the following code, added Constructor, also didn't make TestInner$1.class.
public class TestInner {
private static class Inner {
Inner(){ }
}
public static void main(String[] args){
new Inner();
}
}
I have no idea, so can anyone help me?
EDIT:
I found the same question and it solved. Thank you for your helping.
Why is an anonymous inner class containing nothing generated from this code?
None of your examples have anonymous inner classes. None of them will produce a file named TestInner$1.class. All of them will produce a file named TestInner$Inner.class.
The following example shows an anonymous inner class and will produce TestInner$1.class:
public class TestInner {
public static void main(String[] args){
new Object() {
#Override public String toString () {
return "ninja";
}
};
}
}
I'm not sure where your TestInner$1.class came from but I'm guessing it's left over from previous experiments you were doing.
Update 1: I can confirm that without using Eclipse I get TestInner$1.class (in addition to TestInner$Inner.class -- 3 files are produced) for the first example but not for the last two, just like you are seeing. Will update when I find out why. When compiled via Eclipse, TestInner$1.class is never produced.
Update 2: OP found solution in Why is an anonymous inner class containing nothing generated from this code?.

"The public type <<classname>> must be defined in its own file" error in Eclipse [duplicate]

This question already has answers here:
Java compiler error: "public type .. must be defined in its own file"?
(5 answers)
Closed 9 years ago.
I have written the following code:
package staticshow;
public class StaticDemo {
static int a = 3;
static int b = 4;
static {
System.out.println("Voila! Static block put into action");
}
static void show() {
System.out.println("a= " + a);
System.out.println("b= " + b);
}
}
public class StaticDemoShow {
public static void main() {
StaticDemo.show();
}
}
I am getting the error message:
The public type StaticDemo must be defined in its own file
error in the very first line public class StaticDemo {. Why is it happening and how can I resolve it? Note that my project name is StaticDemoShow, package name is staticshow and class names are as given in the code.
EDIT- After making just one class public or both the classes default, I am getting the error "Selection does not contain a main type". Now what should I do?
If .java file contains top level (not nested) public class, it has to have the same name as that public class. So if you have class like public class A{...} it needs to be placed in A.java file. Because of that we can't have two public classes in one .java file.
If having two public classes would be allowed then, and lets say aside from public A class file would also contain public class B{} it would require from A.java file to be also named as B.java but files can't have two (or more) names (at least in all systems on which Java can be run).
So assuming your code is placed in StaticDemoShow.java file you have two options:
If you want to have other class in same file make them non-public (lack of visibility modifier will represent default/package-private visibility)
class StaticDemo { // It can no longer public
static int a = 3;
static int b = 4;
static {
System.out.println("Voila! Static block put into action");
}
static void show() {
System.out.println("a= " + a);
System.out.println("b= " + b);
}
}
public class StaticDemoShow { // Only one top level public class in same .java file
public static void main() {
StaticDemo.show();
}
}
Move all public classes to their own .java files. So in your case you would need to split it into two files:
StaticDemo.java
public class StaticDemo { // Note: same name as name of file
static int a = 3;
static int b = 4;
static {
System.out.println("Voila! Static block put into action");
}
static void show() {
System.out.println("a= " + a);
System.out.println("b= " + b);
}
}
StaticDemoShow.java
public class StaticDemoShow {
public static void main() {
StaticDemo.show();
}
}
Cant have two public classes in same file
public class StaticDemo{
Change to
class StaticDemo{
Java rule : One public class in one file.
Save this class in the file StaticDemo.java.
Also you cant have more than one public classes in one file.
You can't use 2 public class instances, you need to use one. Try using class (name) instead of public class (name)
error in the very first line public class StaticDemo {
Any Class A which has access modifier as public must have a separate source file as A.java or A.jav. This is specified in JLS 7.6 section:
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).
However, you may have to remove public access modifier from the Class declaration StaticDemo. Then as StaticDemo class will have no modifier it will become package-private, That is, it will be visible only within its own package.
Check out Controlling Access to Members of a Class
You can have only one public class in a file else you will get the error what you are getting now and name of file must be the name of public class
I had two significant errors in my program. From the other answers, I learned in a single java program, one can not declare two classes as "public". So I changed the access specifier, but got another error as added to my question as "EDIT" that "Selection does not contain a main type". Finally I observed I forgot to add "String args[]" part in my main method. That's why the code was not working. After rectification, it worked as expected.

Categories

Resources