terminal not overwriting .class files - java

I am taking a java programming class right now and it is my first real programming experience (although i have done some programming before). for the class i have to use jEdit to write programs, and terminal to compile and run them (i have a mac, and programs that automatically compile, run, and debug programs are banned for educational purposes). things were going very well for me at first, but a few days ago, terminal stopped overwriting the .class files on my QuickSort program when i try to compile it. i change the code so that it will look completely different when it runs, but after i compile and run it, there is no change. however, if i delete the .class files before i recompile, the changes are implemented next time i run it. neither me nor my teacher have been able to find any info on this problem or how to fix it (the exact same thing did happen to a classmate of mine three days before it happened to me, and we are the only mac users in the class). if anyone knows what the problem is, how to fix it, or where i can find someone who does know how to fix it, i would really appreciate it. deleting five .class files every time i compile my program is a huge pain and has already led to some serious problems for me. thank you so much for all of your help!
*edit: i am running mac os x 10.8.5

The compiler isn't smart enough about detecting which class files are out of date, so either manually tell it to recompile everything using javac *.java or use a build tool such as Ant.
The reason the compiler doesn't recompile all of the classes is that it tries to be 'smart' and avoid unnecessary work by only recompiling files that changed. If a .class file is newer than the matching .java file, the source code hasn't changed since the previous compilation so the class isn't recompiled.
This can cause problems when there are multiple files with a chain of dependencies. Consider this simple example:
// file: A.java
public class A { public static void main(String[] args) { new B().run(); } }
// file: B.java
public class B { void run() { new C().run(); } }
// file: C.java
public class C { void run() { System.out.println("hello world"); } }
When A is compiled for the first time, the compiler sees that it references B, which in turn references C. All three are compiled and all is well.
If B.java is modified and A is recompiled, the compiler sees that A references B and since B.java is newer than B.class it is recompiled. It doesn't recompile C because C.java hasn't changed. All is still well.
But if C.java is modified and A is recompiled the compiler sees that A depends on B, but since B.java hasn't changed it is not recompiled. So the compiler never gets to C and doesn't recompile it even though C.java has changed.

Related

Java File runs with java FileName.java command but doesn't compile with javac Filename.java

File name: B.java
public class B
{
public static void main(String[] args){}
}
public class A{}
java B.java runs without error
javac B.java gives a compile error: class A needs to be declared in a file A.java
I understand that a java file can not have more than one public class, but why can a java file run without error using the java command when you get compile errors for the code using javac?
Java-11+ allows launching Single-File Source-Code programs without compiling. You can learn more about it from this article. As per the specification, if the first class in the file has main, it executes the same without caring for other public classes in the file. Thus, if you change the order of classes in the file and try java B.java, it will fail.
My guess, and it is only a guess since I haven't used Java 11 extensively, is that:
The "javac" command produces class files that can be combined into a large program, and thus there could be multiple references to class A "elsewhere" in the program. It is this generality that produces the restriction on one public class per source file (though frankly I don't see why compiling B.java cannot result in A.class and B.class)
The "java" command processes a single source file. From that point of view it is irrelevant whether A is public or not; A can be used from within the single file (same package!) in any case.

Is Java's import keyword for source files or binary files?

I know I can include a class or collection of classes in my Java project using the import statement.
For example, import java.io.utils.* imports (i.e. makes available for use in my Java program) all the classes in the java.io.utils package.
My question is, do the classes in an imported package need to be compiled? Or can packages also include uncompiled Java files? If it can be either, when can we use class files and when can we use Java files?
Import just means "make the imported classes available by their simple names" - you can remove imports entirely if you use fully-qualified names everywhere. It's definitely not like #include in C for example.
When you compile, if you try to refer to uncompiled code it will be compiled at that point, assuming the compiler can guess where to find the source code. The result never refers to uncompiled code, because the compiler needs to know what each type exposes.
As a complete example, construct the following file structure:
// src/foo/A.java
package foo;
import bar.*;
public class A {
public static void main(String[] args) {
B.sayHello();
}
}
// src/bar/B.java
package bar;
public class B {
public static void sayHello() {
System.out.println("Hello");
}
}
Then in the src directory, run:
javac foo/A.java
That will automatically compile bar/B.java - but wouldn't compile any other code that isn't referenced (potentially transitively).
I would strongly recommend against using this "compile on demand" behaviour anyway though - if you compile class A that depends on class B, it will compile B the first time, but after that if you change B and recompile A, the compiler won't recompile B. I would organize your code into appropriate projects, and always recompile a complete project at a time, adding a project's output directory to the classpath for a project that depends on it, rather than allowing compiling one project to recompile bits of another on demand.
(Note that this isn't talking about the incremental compilation that many IDEs support... that's a rather different matter, and is fine assuming it's been implemented properly.)
Unlike C, import in Java does not "copy" stuff. Packages in Java is simply a way of avoiding ambiguity. javax.swing.Timer and java.utils.Timer are different Timers. When you say import javax.swing.Timer, you are telling the compiler that you mean javax.swing.Timer, not any other Timer.
All these things that you can import comes from the JDK or some other libraries you're using, or they are created by you. The classes that fall into the former category is already compiled (.class). The classes you created are compiled as well, when you do javac. You can't refer to any uncompiled classes. Since they are uncompiled, the computer does not know they exist.
The reason why your IDE knows your packages and classes before you compile your code is because IDEs are smart. They compile your code before you even notice it.
As Java documentation reports.
You might have to set your CLASSPATH so that the compiler and the JVM can find the .class files for your types.
link: https://docs.oracle.com/javase/tutorial/java/package/summary-package.html

Issue running java program from batch file, runs fine in IDE

I'm doing some basic java homework for a class on my new laptop - issue is, I can't seem to get the program to compile and run from my batch file using the directions the instructor gave me.
I've set the Path variable to my JDK inside the Environment Variables settings.
My program is a simple shipping program to keep track of shipment information - I have the program working flawlessly in NetBeans (which our instructor advised us to use for developing the code), but he's going to be testing them using batch files, so we're also advised to test them on our systems with one we create prior to turning them in - pretty straightforward.
Issue is, I cannot seem to get this to work. I've never done it before, but I've used .bat files to compile and run C++ programs, as well as using makefiles on a unix system, so I feel like I'm absolutely stupid for not figuring this out on my own, but none of my searches have returned any fruitful solutions that help at all.
My program consists of 3 .java files:
Shipment.java - an interface that contains abstracted methods that are implemented in the ShipmentHW1 class
ShipmentHW1.java - a class that implements the abstracted methods from Shipment and has constructors, etc to create a usable object
TestShipment.java - the main class of this program, which utilizes and creates ShipmentHW1 objects based on preset parameters. This is super duper basic stuff here, and again, it runs perfectly fine inside the NetBeans IDE.
The instructions given to us state to have the batch file inside the package directory (which in this case I've set aside a seperate folder on my desktop titled "shipping", which is the package name - shouldn't be any issues there), where the 3 .java files are located as well.
They say if you don't need to explicitly list the path to the JDK, then you can simply have
javac TestShipment.java
java TestShipment.java
pause
Afterwards I get errors talking about how it "cannot find symbol Shipment s = new ShipmentHW1();"
I've tried adding imports, but since they're in the same package it shouldn't even be an issue.
Directory path is
C:\Users\X\Desktop\shipping
All 7 files are contained within:
TestShipment.java
TestShipment.class
Shipment.java
Shipment.class
ShipmentHW1.java
ShipmentHW1.class
doHW1.bat
Does anyone have any idea? I can provide more information if I've been too vague
Also, I'm on Windows 8 if that makes any difference
Solved
Batch file now reads
javac TestShipment.java Shipment.java ShipmentHW1.java
cd ..
java shipment.TestShipment
pause
and it works like a charm. Anyone have any ideas why I had to call the package.class instead of just compiling it regularly?
Try doing
javac TestShipment.java
java TestShipment
pause
Without seeing the contents of TestShipment.java, I'll assume you have some dependency on the Shipment and ShipmentHW1 classes. As such, when you execute a program that uses the TestShipment class, you need to have the .class files for each of the three (and any other dependencies).
So you will have to compile Shipment.java and ShipmentHW1.java as well before running your java command. If they are in the same package, you're good, if not, you will have to specify an appropriate value for the -cp option.
When running java with a class name, you need to specify the fully qualified class name.
If your .java files are declared to be in the 'shipping' package, then you probably need to be running java from the parent directory of 'shipping', e.g.
cd <path>/shipping
javac TestShipment.java
cd ..
java shipping/TestShipment

How Java compilation works?

I have a question about java compilation or sequence of java file compilation.
Question - I have a small object oriented program where I have three classes. I wrote java code for the biggest one where I am creating the objects for other two classes and invoking the methods from other two classes. other two classes are very small. When I compiled the first class file (without writing other two class files), I got few compilation error messages. Then I wrote both new class files (but I didn't compile them, only .java files), my first class file compiled fine.
--So I want to understand, do I need to compile all the Java files to get all object references in those classes working or just writing java files is fine to compile any of these?
If you compile the one that refers to all the others, they will be compiled automatically as soon as Compiler encounters them in your code.
I would use a build system like maven, ant or your IDEs build system. This means you don't need to worry about these issues.
In answer to your question; it depends. You often don't need to compile everything, javac can compile more than one source file at once, sometimes you have to rebuild dependencies.

Can't compile an application using Eclipse, Maven, and the Android Plugin for Maven

I'm trying to create an Android application in Eclipse using the Maven plugin and the m2eclipse-android-plugin as well. Things were going "ok" until recently. I'm using Helios on Ubuntu and have the latest JDK (removed the default one installed by Ubuntu).
The project references two libraries that I've also created. One is an Android specific utility project and generates the .apklib (successfully). The other library is a more general purpose set of utilities not specific to Android which produces a JAR file. Both of these projects are also built using the Maven plugin for Eclipse. In addition, I've verified that both the .apklib and .jar files are in the local repository and both included all of the generated class files as would be expected.
When it goes to build the .apk file, I'm getting a "cannot find symbol" on a class in my Android project where the symbol is a class from the non-Android utility JAR file. For some completely bizarre reason, the class file cannot be found inside the JAR file. I verified that, in fact, the JAR file is in my local maven repository and that the class file is in the JAR file. I've also run the maven install command with debugging on, copied the command line that gets fed into the Java compiler. When I execute that command in a console, I receive the SAME error (indicating that it's a Java compiler error and not a Maven error).
Has anyone else run into this type of situation before? It's extraordinarily strange and I've completely combed the command line for potential issues and, best as I can tell, everything seems correct.
Well, through what appears to be trial and error I seem to have fixed the problem. I had a file that looked "similar" to this:
import Test.TestObserver;
import com.myself.ImportedClassThatCouldntBeFound;
class Test extends ImportedClassThatCouldntBeFound {
public interface TestObserver {
public void event ();
}
public void addObserver (TestObserver observer) {
...
}
}
public class AnotherTest {
private Test test = new Test ();
public void blah () {
this.test.addObserver (new TestObserver () {
public void event () {
...
}
});
}
}
The problem happened at the TOP of the file. For some reason, Eclipse imported the inner interface!
When I "REMOVED" that import, and then changed AnotherTest to:
public class AnotherTest {
private Test test = new Test ();
public void blah () {
this.test.addObserver (new Test.TestObserver () {
public void event () {
...
}
});
}
}
it compiled correctly! I even verified it by putting the import BACK into the file and removing the fully declared interface name and it caused it to fail again! It's definitely one of the craziest compiler issues I've ever seen and once I get back the FOUR HOURS of my life that I lost researching this, I'll do more investigation into why this is occurring.
This will be the first time I do this on StackOverflow, but I'm going to mark this as the solution because it most definitely was the issue. However, it definitely requires more research (at least on my part) to try and understand what was causing the compiler to become so confused.
edited this to make it apparent that the class that had the inner interface was extending the class that could not be found when compiled
To me, it looks like a problem caused (ultimately) by putting two top-level classes into a single source code file. This is generally thought to be bad practice.
It is not clear whether the compilation error is mandated by the JLS, whether it is a bug in the Java compiler. But either way, the best fix is to not put multiple classes into one source file.

Categories