I have Exception in thread "main" java.lang.NoClassDefFoundError: A (wrong name: a) and I dont't have any idea what this can caused by
public class Test
{
public static void main(String[] args)
{
new B();
}
}
interface a { }
class A implements a { }
class B extends A { }
Edit: in online compiler https://www.onlinegdb.com/online_java_compiler it compiles
When Java compiles your source code, it creates multiple .class files. For example, it creates Test.class for public class Test, a.class for interface a, and A.class for class A. The problem here is that file names in some operating systems are case-insensitive. This means that the operating system sees a.class and A.class as the same file so one will overwrite the other.
The online compiler most likely treats these file names as different due to case-sensitivity.
The solution here is to use different names so that you avoid these name collisions at the operating system level.
The established Java convention is to start all class and interface names with an upper case letter. If you follow this convention, then you will avoid this problem.
If you run javac path/to/your/file, you should see the list of .classfiles created by the java compiler in that dir. The problem with your approach is you have duplicate names for the interface and the class i.e A (case insensitive) and as a result only one .class gets created. Try again by changing the name of either interface or class and your problem should go away.
Related
I would like to be able to add a file with the java structure and extension into my program to an arraylist via outside the actual program directory/jar.
Ex,
Test.java, located at C:\Users\user\Desktop\Test.java (Outside the jar)
public class Test extends Object {
public Test() {}
public void someMethod() {}
}
MyProgram.java
import java.util.ArrayList;
public class MyProgram extends Object {
public MyProgram() {}
public void readIn() {
ArrayList<Object> list = new ArrayList<Object>();
list.add(Test.java);
}
}
Obviously a lot more will have to be done but hopefully you understand the point.
Read In Test.java -> Convert it somehow so it's added to the arraylist due to it's extension. So if the extension was Family instead of Object, the arraylist would be ArrayList instead and Test extends Family.
Edit
As stated by a comment, this is an approach to a plugin mechanism.
The answer to this question stems from Seelenvirtuose's suggestion along with crick_007. To access classes outside the class path, simply create a ClassLoader and load the class in.
You must also use an interface to interact between the two classes, also knowing what methods are provided. Lastly, packaging must also be the same or else you'll get errors such as
PACKAGENAME.CLASS cannot be cast to PACKAGENAME.CLASS even if the class has the same name as in your program (A test I tried)
I create a class named CAR and I also created an interface named car.
They both in a same source file. I make the CAR class implements the car interface and the IDE shows nothing wrong. But when I run this program, it gives an error that is
Exception in thread "main" java.lang.NoClassDefFoundError: test/car (wrong name: test/CAR)"
Why is that ? JAVA is not case sensitive, is it?
Here's the code:
package test;
interface car {
void changespeed(int x);
void changeoil(int x);
}
class CAR implements car {
private int speed;
private int oil;
public CAR(int _speed,int _oil) {
speed = _speed;
oil = _oil;
}
public void changespeed(int x) {
speed = x;
}
public void changeoil(int x) {
oil = x;
}
public void Show() {
System.out.printf(speed + " " + oil);
}
}
public class test {
public static void main (String[] args) {
CAR a = new CAR(100,200);
a.changespeed(200);
a.changeoil(200);
a.Show();
}
}
Technically, you can do this on some platforms.
It will work on Linux / UNIX
It will probably work on Mac OSX, though you may need to tweak things to turn of "user-friendly" case-insensitivity.
However, it is a bad idea to make your code-base dependent on the platform's ability to do case-sensitive pathname lookup. And it is also a bad idea to ignore the Java Style Conventions which clearly state that:
you should not define identifiers of the same kind that differ only in case,
you should always start a class name with an uppercase letter, and
all uppercase is reserved for constants.
The problem is that the standard Java mechanism for finding the file in which a class lives relies on being able to map the class name to a file name, on the assumption that filenames are case sensitive. If you follow the Java style guidelines, the mechanism works on all platforms. If you (wilfully) don't, you are going to be in for a world of pain ... and you won't get much sympathy.
(But if you managed to put your compiled classes into a JAR file with the correct casing for the class names, that should work even on Windows. Not sure of a good way to do that though ... if you are building on Windows.)
So, to answer your question:
why can't i use similar word as java class name and interface name which just case differs?
Because you are using Windows, and because you are ignoring Java style rules.
JAVA is not case sensitive, is it?
Yes it is.
I should also point out that Show() is a style violation, and so are changespeed(...), changeoil(...) and _speed, and _oil.
If you are writing code that only you will ever read, then you can (mostly) get away with ignoring style. But if you write code that other people will / might have to read, then you are liable to get a lot of criticism.
Java is case sensitive, it's the file-system that's causing you trouble. You'd better follow naming conventions.
Typically, compiling one .java file might give you multiple .class files. Basically each class in the source file goes into one .class file.
In your case, the compiler is trying to generate three files: car.class, CAR.class and test.class. In a file-system that treat CAR.class and car.class as the same file, you are going to have trouble. Similar issues arise when we try to unzip something created under a Linux system, where under the same folder there's two file names differ only in letter case.
Solution? Follow the naming convention. Basically you have to rename the interface or the class somehow:
interface Car {}
class MyCar implements Car {}
As #Luke Lee said, Windows files system is case insensitive.
If you compile your test.java program, it should makes class file named after their class name:
> javac test.java
CAR.class
car.class
test.class
but in Windows, CAR.class and car.class file names are considered as same file name.
So in run time, java.lang.NoClassDefFoundError occurs.
Given a Java source file named as TestMainFunction.java
1.) As most of us would know, a Java file name must be the class name which contains the main function
See the below simple code (in a single file named as mentioned above) which executes perfectly and prints ClassOne.
public class TestMainFunction {}
class ClassOne {
public static void main(String[] a) {
System.out.println("ClassOne");
}
}
2.) When there is more than one class with a main function in a single file, Eclipse prompts the user to choose the class to run.
See the below simple code (single file named as mentioned above) which executes perfectly and prints the class name as we have chosen from the Eclipse promt.
public class TestMainFunction {
public static void main(String[] a) {
System.out.println("TestMainFunction");
}
}
class ClassOne {
public static void main(String[] a) {
System.out.println("ClassOne");
}
}
class ClassTwo {
public static void main(String[] a) {
System.out.println("ClassTwo");
}
}
All the above will work as I mentioned. It will create separate .class file for every class. The same behavior applies even when using inner classes.
But what exactly is happening here? How does Eclipse know which class to launch when multiple classes are present in one source file? Can any one explain it? Explaining this would be greatly appreciated.
As most of you would know, a Java file name must be the class name
which contains the main function
This is incorrect, and I believe the source of your confusion. A Java source file is only allowed to have one public class, and it must have the same name (minus the extension) as it's containing file. A given Java source file though, may contain as many non-public class files as desired, with the only constraint being that their names are valid. Note that you can have a class with the same name as its containing source file (minus the extension) that is not public! Also note that it's generally considered bad practice to have multiple top-level (non-nested) classes in a single Java source file.
The second assumption you may have is that only one class in a source file is allowed to have a main function. This is simply untrue. You can add a main function to every single one of your class files - the only one that matters is the one you specify to the JVM when your application is being launched.
So given your scenario - a source file with multiple class files (one of them public), where each class has a main method, the following applies:
When you invoke the Run command in Eclipse on this file, Eclipse will detect that there is more than one eligible class to be run, and will prompt you to select one of those class. It will then build a 'Run Profile' for the selected class, that launches just that class. You can actually see the profile Eclipse builds via the Run->Debug Configurations menu.
When compiling this source file externally, it will generate multiple .class files (not just one). The classes had no relation to each other save being in the same source file, and you would explicitly select the .class you want to launch in the JVM.
i.e:
java TestMainFunction
java ClassOne
java ClassTwo
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"}
I have found one error in my Java program:
The public type abc class must be defined in its own class
How can I resolve this error? I am using Eclipse. I am new to Java programming.
Each source file must contain only one public class. A class named ClassName should be in a file named ClassName.java, and only that class should be defined there.
Exceptions to this are anonymous and inner classes, but understanding you are a beginner to Java, that is an advanced topic. For now, keep one class per file.
Answering your addition: it is OK to inherit classes and that's totally fine. This does not matter, each class should still have its own file.
Public top-level classes (i.e. public classes which aren't nested within other classes) have to be defined in a file which matches the classname. So the code for class "Foo" must live in "Foo.java".
From the 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 rule, which doesn't have to be followed by compilers, is pretty much universally adhered to.
Ok, maybe an example will help.
In file MySuperClass.java:
public class MySuperClass {
// whatever goes here
}
public class MySubClass1 extends MySuperClass {
// compile error: public class MySubClass1 should be in MySubClass1.java
}
class MySubClass2 extends MySuperClass {
// no problem (non-public class does not have to be in a file of the same name)
}
In file MySubClass3.java:
public class MySubClass3 extends MySuperClass {
// no problem (public class in file of the same name)
}
Does that make things clearer?
A public class with the name of "abc" must be in a file called abc.java
You can create a new class an a existing file if it's private, but you should not do this.
Create one file per class.
Eclipse does that for you, if you create a new class.
For programming Java, you have to understand the construct of classes, packages and files. Even if Eclipse helps you, you have to know it for yourself. So start reading Java books or tutorials!