Java cannot find enum in the other class - java

I wrote down a Enum class which could successfully compile, and then whenever I use the Enum class as a type of variable in the other class of the same package, the "cannot find symbol" would occur when compiling.
Here is the code for Enum:
package cards;
public enum CardType {
NIGHTMUSHROOM,DAYMUSHROOM,CIDER,BUTTER,PAN,BASKET,STICK
> }
And then I use the Enum in another class, I tried to import while the two pieces of code are in the same package so there is no use for the error.
package cards;
//import static cards.CardType;
public class Card{
protected CardType type;
protected String cardName;
public Card(CardType newType,String newName){
this.type = newType;
this.cardName = newName;
}
public CardType getType(){
return this.type;
}
public String getName(){
return this.cardName;
}
}
However when I compile Card class, I report the error message like below
I have looked at some of the questions about enum in the forum while they couldn't make sense for my code.

The CardType class's full name is cards.CardType (it's the package name, plus a dot, plus the classname). Hence, when javac is attempting to compile Card.java, it looks for the class cards.CardType. To find it, it scans the classpath roots for the path /cards/CardType.class.
It can't find this file, hence, error.
The 'root' that you need to make this work is the parent directory of whereever Card.java lives. After all, if you start at that path and 'dir' into cards and then look for CardType.class, that'll work. It's generally a good idea to stay in this 'root' instead of CDing into subdirs from there.
Hence:
cd /home/tianyue/projects/myawesomeproject
ls; -- prints: "cards"
ls cards; -- prints: "CardType.java Card.java"
javac cards/CardType.java
javac cards/Card.java
Will work fine unless you've been messing with settings and removed . as default path. You can always forcibly add it - javac -classpath . cards/Card.java instead. Or, much simpler:
javac cards/*.java
Note that most folks will use a build system such as gradle or maven, or an IDE, to take care of building projects. Once you involve multiple packages and dependencies, trying to command-line your way through a compilation process with just javac invokes gets real tedious.

Related

How to run a java .class file that extends a Class which is in another directory?

I first met this problem in my Ideas, I wrote a Class that extends javax.servlet.http.HttpServlet, My Ideas throws an error message reads Error: Could not find or load main class com.bjpowernode.OneServlet, here is the image:
enter image description here
It can be seen that Idea didn't show the red wavy line, that shows my codes are fine. I found a solution to this problem from enter link description here, I changed the scope from provided to compile:
enter image description here
But I actually want to know why and how it works? I compared the difference of Idea compilation instructions under different scope setting,I found that when Idea uses java command to run the .Class, the parameter -classpath of the command of the compile scope has two more paths:
D:\apache-tomcat-8.0.50\lib\jsp-api.jar;D:\apache-tomcat-8.0.50\lib\servlet-api.jar
That's to say, Idea didn't consider external library paths when run .class under the provided scope, and the super Class HttpServlet is from servlet-api.jar package. Why?
To simplify the problem, I created two different classes under two different paths and packages: Class Base and Class Sub, and Sub extends Base.
The codes of the Base is here:
package base;
public class Base{
public static void main(String[] args) {
}
}
The codes of the Sub is here:
package sub;
import base.Base;
public class Sub extends Base{
public static void main(String[] args) {
System.out.println("In Sub");
}
}
The path of Base is ./path1/base/Base.java and the path of Sub is ./path2/sub/Sub.java.
I compiled them using these two commands:
javac ./path1/base/Base.java -d ./path1
javac ./path2/sub/Sub.java -d ./path2 -cp "./path1;./path2"
And compiled successfully. But when I run sub.Sub using the command below:
java sub.Sub -cp "./path1;./path2"
And I got the same error:
Error: Could not find or load main class sub.Sub
Ive tried multiple variations of this, but none of them seem to work. Any ideas? Although I solved the problem of idea reporting errors, I still could not understand the principle behind? I hope this question can help me to figure it out. My jdk version is 1.8. Thanks in advance.

Why can't I have a java class name and interface name that only differ in letter case?

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.

Change name of a Class

Is it possible to change the name of a class retrieved using:Foo.class.getName() (or getSimpleName() or getCanonicalName()).
I know that those methods are part of java.lang.Class<T> the question itself is if there is a way to tell java.lang.Class<T> what is the name that I want it to display for my class.
I know that it "opens the door to tricky things" since that name is used by the reflection libraries to do "stuff" and bla bla bla. nevertheless I was wondering wether is posible to call Foo.class.getSimpleName() and get something like MyFoo.
All of this of course without string manipulation which is the last alternative I have.
Find the src.zip in your JDK. Extract java/lang/Class.java into some directory and modify getSimpleName() method. For example like this:
public String getSimpleName() {
return "MyName"; // return MyName for any class
}
Compile it normally with javac (you will get many warnings, ignore them). Remove all additional classes created like Class$1.class, leaving only java/lang/Class.class file. Put it into jar:
$ jar -c java >myclass.jar
Now prepend the bootstrap path with your new jar. For example, let's consider this test class:
public class Test {
public static void main(String[] args) {
System.out.println(Test.class.getSimpleName());
}
}
$ java Test
Test
$ java -Xbootclasspath/p:myclass.jar Test
MyName
I don't even want to explain how dangerous it is. Also according to the Oracle binary code license (supplemental term F) you cannot deploy your application this way.
You may try Powermock which according to their home page allows mocking final classes although it needs to use it's own class loader.
Other mocking frameworks that do not do byte code manipulation with custom class loaders such as Mockito and Easymock cannot work with classes that are final which java.lang.Class is.

ant java compile throwing cannot find symbol

I am working on a project that is having a layered Architecture.
I have a interface ABC and in that interface I have a enum XYZ
For ex
public interface ABC {
public enum XYZ {
CONSTANT1("SOMETHING"),
CONSTANT2("SOMETHING3");
final String name;
private TYPE(String name) {
this.name=name;
}
public String getName() {
return this.name;
}
}
}
I am compiling this using ant and using this jar file in other layer. In that layer I am trying to access it like
String name=ABC.XYZ.CONSTANT1.getName();
I am getting symbol not found error during compile. I verified classpath is set properly.
I am using ant v 1.8 and java 1.6.
Why I am getting this error ?
First of all, don't nest the enum in an interface. It's perfectly fine that it has its own source file named after the enum.
Second, I assume you mean XYZ instead of TYPE in your private constructor?
Last, you should be able to use it in that way, no matter if compiled via ant or within eclipse or directly using javac. Probably you have not compiled everything - the way you did it, there should be ABC.class (the interface), ABC$XYZ.class (the inner enum) and the class file of your calling class.

Classes in same package

I love the Intellij IDEA but i have been stacked on one little problem with Java imports.
So for example there is a package with name "example" and two different classes in it: A.java and B.java.
And i wanna get access to class "A" from class "B" without imports. Like this:
class A:
package example;
public class A{ ... some stuff here ...}
class B:
package example;
public class B{
public static void main(String[] args){
A myVar = new A();
}
}
This code may not work, but it's doesn't matter. Trouble just with IDE and with its mechanism of importing classes.
So, problem is that i can't see A class from B. Idea says 'Cant resolve symbol' but i actually know that class A exists in package. Next strange is that complier works fine and there are no exceptions. Just IDEA can't see the class in the same package.
Does anybody has any ideas?
If they are in the same package, you can access A in class B without import:
package example;
public class B{
public static void main(String[] args){
A myA = new A();
}
}
Maybe this will help you, or somebody else using IntelliJ that is getting a "Cannot resolve symbol" error but can still compile their code.
Lets say you have the two files that buymypies wrote up, the standard Java convention is that the two files would exist in an Example directory in your source code area, like /myprojectpath/src/Example. But it is technically not a requirement to reflect the package structure in the source directory structure, just a best practice sort of thing.
So, if you don't mimic the package structure, and the two files are just in /myprojectpath/src, IntelliJ will give you the "Cannot resolve symbol" error because it expects the source code structure to reflect the package structure, but it will compile okay.
I'm not sure if this is your problem, but I do use IntelliJ and have seen this, so it's something to look at.
I have the same problem as this: 2 classes in the same package, yet when one tries to call the other, Intellij underlines it in red and says Cannot resolve symbol 'Classname', e.g. Cannot resolve symbol 'LocalPreferencesStore'.
It then wants to add the fully qualified name in situ - so it clearly knows the path - so why can't it just access the class?
The module still compiles and runs, so it's just the IDE behaving oddly - and all that red is very distracting, since it isn't actually an error, it's just IDEA throwing a weird wobbly.
This is also recent. Two weeks ago I wasn't having this problem at all, and now suddenly it's started up. Of course, it could go away again on its own soon, but it's really annoying.
Same issue and I just fixed it.
I don't know your folder structure.
However, if your package example was added manually.That's the problem.
The package should be the same as your folder structure,which means if you want your class file to be stored in package example,you must store you java file in the src's subfolder named example.
You need to learn the basics about Java i think.
Here is a basic example of what i think you are trying:
package Example;
public class A
{
String myVar;
public String getMyVar()
{
return myVar;
}
public void setMyVar(String myVar)
{
this.myVar = myVar;
}
}
You need to create an instance of A.
package Example;
public class B
{
/**
* #param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
A myA = new A();
myA.setMyVar("Hello World!");
System.out.println(myA.getMyVar);
}
}
Look up java 'getters' and 'setters'.

Categories

Resources