I have a pile of .java files. They all have the same class name public MyClass. They all have a main method. They all may or may not have a package declaration at top, and I do not know ahead of time.
I am trying to write a script to compile and run these java programs. This is easy for the files without the package declaration... I just do some cp operations to setup, javac MyClass.java and java MyClass, then rm to teardown. However, the files with the package declaration require special attention. I have a few options that occur to me, including deleting the package lines, or attempting to read the package lines so that I know what the resulting directory structure should be. Both of these require me to go parsing through the .java files, which makes me sad.
Is there a way to compile and run these files without having to parse the .java files? Something like:
javac --ignore_package_structure MyClass.java
would be ideal, but a quick look at the javac man pages suggests that such a thing doesn't exist.
If we can assume that each student submits a single source file named HelloWorld.java, then we can use the "Launch Single-File Source-Code Programs" feature added by JEP 330 in Java 11:
java HelloWorld.java
We don't run javac first, we don't get a .class file (no cleanup needed), and any package declaration is handled automatically.
Remember, the students are still allowed to use many classes, they just all have to be submitted to you in a single source file.
The name of the class doesn't even matter. The first class in the source file is executed.
There isn't any easy way to do this. You could use regex though, and replace all imports with this simple java regex:
"package \w+;"g
Simply stated, you create a Java program to replace all the package names.
How to replace files: Find and replace words/lines in a file
Related
I'm a C++ developer - not a java developer, but have to get this code working...
I have 2 public classes that will be used by another product. I used the package directive in each of the java files.
package com.company.thing;
class MyClass ...
When I try to compile a test app that uses that I add
import com.company.thing.*;
The javac compiler fails with errors about com.company does not exist. (even if I compile it in the same directory as the class files I just made a package of)
I am sure I am doing something bone-headed and silly.
I've read the http://java.sun.com/docs/books/tutorial/java/package/usepkgs.html pages and tried to set up a directory structure like /com/company/thing etc, but either I have totally screwed it all up or am missing something else.
EDIT
thanks for the suggestions - I had tried the classpath previously. It does not help.
I tried compiling
javac -classpath <parent> client.java
and the result is:
package com.company does not exist
I have the code I want to import (the two java files) in \com\company\product. I compile those fine. (they contain MyClass) I even made a jar file for them. I copied the jar file up to the parent directory.
I then did (in the parent directory with the client java file)
javac -cp <jarfile> *.java
the result is:
cannot access MyClass
bad class file: MyClass.class(:MyClass.class)
class file contains wrong class: com.company.product.MyClass
Please remove or make sure it appears in the correct subdirectory of the classpath.
EDIT
I got the client code to compile and run if I used the fully qualified name for MyClass and compiled it in the parent directory. I am totally confused now.
compiled with no classpath set - just
javac *.java
in the parent directory - and it worked fine.
I can get a test app to compile, but that is not going to cut it when i have to integrate it into the production code. Still looking for help.
EDIT:
Finally - not sure why it didn't work before - but I cleaned up all the files all over the directory structure and now it works.
Thanks
Okay, just to clarify things that have already been posted.
You should have the directory com, containing the directory company, containing the directory example, containing the file MyClass.java.
From the folder containing com, run:
$ javac com\company\example\MyClass.java
Then:
$ java com.company.example.MyClass
Hello from MyClass!
These must both be done from the root of the source tree. Otherwise, javac and java won't be able to find any other packages (in fact, java wouldn't even be able to run MyClass).
A short example
I created the folders "testpackage" and "testpackage2". Inside testpackage, I created TestPackageClass.java containing the following code:
package testpackage;
import testpackage2.MyClass;
public class TestPackageClass {
public static void main(String[] args) {
System.out.println("Hello from testpackage.TestPackageClass!");
System.out.println("Now accessing " + MyClass.NAME);
}
}
Inside testpackage2, I created MyClass.java containing the following code:
package testpackage2;
public class MyClass {
public static String NAME = "testpackage2.MyClass";
}
From the directory containing the two new folders, I ran:
C:\examples>javac testpackage\*.java
C:\examples>javac testpackage2\*.java
Then:
C:\examples>java testpackage.TestPackageClass
Hello from testpackage.TestPackageClass!
Now accessing testpackage2.MyClass
Does that make things any clearer?
Yes, this is a classpath issue. You need to tell the compiler and runtime that the directory where your .class files live is part of the CLASSPATH. The directory that you need to add is the parent of the "com" directory at the start of your package structure.
You do this using the -classpath argument for both javac.exe and java.exe.
Should also ask how the 3rd party classes you're using are packaged. If they're in a JAR, and I'd recommend that you have them in one, you add the .jar file to the classpath:
java -classpath .;company.jar foo.bar.baz.YourClass
Google for "Java classpath". It'll find links like this.
One more thing: "import" isn't loading classes. All it does it save you typing. When you include an import statement, you don't have to use the fully-resolved class name in your code - you can type "Foo" instead of "com.company.thing.Foo". That's all it's doing.
It sounds like you are on the right track with your directory structure. When you compile the dependent code, specify the -classpath argument of javac. Use the parent directory of the com directory, where com, in turn, contains company/thing/YourClass.class
So, when you do this:
javac -classpath <parent> client.java
The <parent> should be referring to the parent of com. If you are in com, it would be ../.
You got a bunch of good answers, so I'll just throw out a suggestion. If you are going to be working on this project for more than 2 days, download eclipse or netbeans and build your project in there.
If you are not normally a java programmer, then the help it will give you will be invaluable.
It's not worth the 1/2 hour download/install if you are only spending 2 hours on it.
Both have hotkeys/menu items to "Fix imports", with this you should never have to worry about imports again.
The standard Java classloader is a stickler for directory structure. Each entry in the classpath is a directory or jar file (or zip file, really), which it then searches for the given class file. For example, if your classpath is ".;my.jar", it will search for com.example.Foo in the following locations:
./com/example/
my.jar:/com/example/
That is, it will look in the subdirectory that has the 'modified name' of the package, where '.' is replaced with the file separator.
Also, it is noteworthy that you cannot nest .jar files.
Just add classpath entry ( I mean your parent directory location) under System Variables and User Variables menu ...
Follow : Right Click My Computer>Properties>Advanced>Environment Variables
I am a beginner in Java and I've built a class "Employee" and a test program "EmployeeTest". From the command line, I have typed javac *.java.
It compiled both files and created Employee.class and EmployeeTest.class.
How do I run those now?
Thanks so much
Assuming Employee.class and EmployeeTest.class are in the same directory, and both do not specify package (they use default package) and EmployeeTest.class contains the main method...you can use this:
java EmployeeTest
The easiest way is to install an IDE which contain a compiler, interpreter, or both, such as NetBeans and Eclipse.
You will be able to run and compile your code easily.
You can run your application using the java <Classname> command. Replace the class name property with your own, e.g. EmployeeTest. If you are having problems, watch your case, since the class name is case sensitive. Also omit the .java file extension, Java needs to know the class name here.
So in your case, try running this from the command line:
java EmployeeTest
So I'm completely new to programming, and I've been writing some Java with the NetBeans IDE. My code runs fine within NetBeans, but I've tried to run it using the command line as well. However, if I run it from the command line, I have to delete the line:
package firstprogram;
which NetBeans automatically places at the top of each new file, or I get the error:
Error: Could not find or load main class FirstProgram
However, if I do delete the line, then the program no longer runs within NetBeans! It doesn't seem right that I have to choose whether to run a .java from within NetBeans or without.
The research I've done makes me think that this is something to do with directory structure? But everything I read on that goes straight over my head. NetBeans has a structure with "build", "dist", "nbproject", and "src", but when I use the command line I just place the .java file in an empty directory and javac from there.
Any explanation is appreciated! The books and tutorials I'm learning from either assume you're just using NetBeans or don't have the package line at all.
You can compile your class using javac command from anywhere, as long as you provide correct relative or absolute path. The problems come when you want to run your program using the java program.
You have to provide the correct path corresponding to your package declaration. For example, if I had 'MyClass' in package mypackage, first line would look like this:
package mypackage;
class source stored on disk:
c:/MyNetbeansProject/src/mypackage/MyClass.java
Compiled bytecode:
c:/MyNetbeansProject/build/classes/mypackage/MyClass.class
Now, if I would have opened a command prompt/terminal in folder c:/MyNetbeansProject/build/classes/, I could run the program using java mypackage/MyClass or java mypackage.MyClass.
However, if i would be somewhere else, I would have to say where the class files are located using the cp option: java -cp c:/MyNetbeansProject/build/classes mypackage/MyClass. The path in cp option can be relative or absolute, use "" when it contains spaces.
Package are directory architecture.
If your class is in the package com.acme.test, the class should be in the com/acme/test directory.
Instead of placing your class in an empty folder, place it in a folder named firstprogram and do javac firstprogram/youclass.java
The package (and folder) permit you to arrange your architecture with logical pattern.
More info here : http://www.tutorialspoint.com/java/java_packages.htm
So like OcterA said, you should keep organized, but with only one class this is not the issue. I believe that your problem is that you are not entering the correct command into the command line.
First cd to the correct directory and when you want to execute a file within a package in that directory you need to enter
java packageName.className
In this case
java firstprogram.FirstProgram
I'm trying to run .class file from command line. It works when I manually move to the directory it's stored in, but when I try something like this:
java C:\Peter\Michael\Lazarus\Main
it says it can't find the main class. Is there any solution to this other than making a .jar file (I know that .jar is the best solution, but at this moment isn't the one I'm looking for)?
The Java application launcher (a.k.a java.exe or simply java) supports up to four different ways to specify what to launch (depending on which Java version you use).
Specifying a class name is the most basic way. Note that the class name is different from the file name.
java -cp path/to/classFiles/ mypackage.Main
Here we start the class mypackage.Main and use the -cp switch to specify the classpath which is used to find the class (the full path to the class mypackage.Main will be path/to/classFiles/mypackage/Main.class.
Starting a jar file.
java -jar myJar.jar
This puts the jar itself and anything specified on its Class-Path entry on the class path and starts the class indicated via the Main-Class entry. Note that in this case you can not specify any additional class path entries (they will be silently ignored).
Java 9 introduced modules and with that it introduce a way to launch a specific module in a way similar to how option #2 works (either by starting that modules dedicated main class or by starting a user-specified class within that module):
java --module my.module
Java 11 introduces support for Single-File Source Code Programs, which makes it very easy to execute Java programs that fit into a single source file. It even does the compile step for you:
java MyMain.java
This option can be useful for experimenting with Java for the first time, but quickly reaches its limits as it will not allow you to access classes that are defined in another source file (unless you compile them separately and put them on the classpath, which defeats the ease of use of this method and means you should probably switch back to option #1 in that case).
This feature was developed as JEP 330 and is still sometimes referred to as such.
For your specific case you'd use option #1 and tell java where to look for that class by using the -classpath option (or its short form -cp):
java -classpath C:\Peter\Michael\Lazarus\ Main
If your Main.java contains the entirety of your source code (and it is in the same directory), then you can use option #4, skip the compile step and directly compile-and-execute it:
java c:\Peter\Michael\Lazarus\Main.java
Assuming that Main.class does not have a package declaration:
java -cp C:\Peter\Michael\Lazarus\ Main
Java looks for classes in a "classpath", which can be set on the command line via the -cp option.
I just had the same issue, I tried running java hello.class, this is wrong.
The command should be java hello.
Do not include the file extension. It is looking for a class file, and will add the name on its own.
So running 'java hello.class' will tell it to go looking for 'hello.class.class' file.
Try this:
java -cp C:\Peter\Michael\Lazarus Main
You need to define the classpath.
I'm trying to figure out how organize source and class files working with packages. I found a very useful tutorial. But I still have some questions.
As far as I understood it is a good practice to have an isomorphism between name of packages and name of the directories where elements of a package are stored. For example if I have a package named aaa.bbb.ccc which contains class ddd it is a good practice to have a class file called "ddd.class" and located in "$CLASSPATH/aaa/bbb/ccc/". Did I get it right?
If it is the case, will Java compiler put *.class files into the correct directory automatically?
I was not able to get this behavior. I set the $CLASSPATH variable to "/home/myname/java/classes". I executed javac KeyEventDemo.java which contains package events;. I expected that javac will create a subdirectory events under /home/myname/java/classes and put the KeyEventDemo.class in this subdirectory.
It did not happen. I tried to help to javac and created "events" subdirectory by myself. I used javac again but it does not want to put class files under "/home/myname/java/classes/events". What am I doing wrong?
You need to use the -d option to specify where you want the .class files to end up. Just specify the base directory; javac will create any directories necessary to correspond to the right package.
Example (based on your question):
javac -d ~/java/classes KeyEventDemo.java
For example if I have a package named
"aaa.bbb.ccc" which contains class
"ddd" it is a good practice to have a
class file called "ddd.class" and
located in "$CLASSPATH/aaa/bbb/ccc/".
Did I get it right?
That's not "good practice" - this is how the Sun JDK expects things to be. Otherwise, it will not work. Theoretically, other Java implementations could work differently, but I don't know any that do.
If it is the case, will Java compiler
put *.class file into a correct
directory automatically?
Yes
What am I doing wrong?
The source code must also already follow this structure, i.e. KeyEventDemo.java must reside in a subdirectory named "events". Then you do "javac events/KeyEventDemo.java", and it should work.
It is not only good practice but a must in most cases.
consider a Java class named:
com.example.Hello
If you store it on the filesystem, it has to got to
/path/to/my/classes/com/example/Hello.java
The compiler (or at least the vast majority) will create the class file at
/path/to/my/classes/com/example/Hello.class
Personally I would not use the CLASSPATH variable to set the path but the -cp option on java. A call to the above "application" could be done with:
java -cp /path/to/my/classes com.example.Hello