I got known and also experienced that JVM does lazy loading classes, that is, even the class is imported, it will not be loaded if this class is not used, it is loaded only when it's actively needed.
I am not sure do JDK constantly use this lazy loading strategy or another implementation will be used in some cases, any JDK specification or doc make this clear?
I have this question is because that I ship class which import some class that is not present and will not be used.
Below program say Yes,
package code;
import code.one.Test1;
public class code {
public static void main(String[] args) {
Test1 test1=null;
}
private static void callmethod() {
}
}
package code.one;
public class Test1 {
static{
System.out.println("hello");
}
}
But in main method if you write Test1 test1=new Test1(); instead of Test1 test1=null; you will get the o/p
Related
So I have two projects A and B, and project B is imported in project A, and in project B I want to initialize some objects which have static initializers.
The problem is, they aren't getting called (already tested with final keyword, does not help).
So I actually want to have a small system and it should go this way (every class decribed here are in project B):
class A is a main class in which you can call a method addClassToLoad()* to add other classes (which will be "loaded" when method start() in class A will be called);
classes B, C and D call method addClassToLoad() from its static initializer;
when some class from project A calls a method start(), class A lists all classes it has gotten and calls a method onLoad() (explained in *).
And every method is static, so it's meant to be only one (no "instancing").
Saddly, static initializers aren't getting called.
And the question is: do I do something wrong (or maybe it is not possible at all) or maybe there is another way to do this small system? (I just don't really want to write in class A about every class, which must be loaded at start() method)
*addClassToLoad() takes an interface which has one method onLoad(), so it is getting called when method start() is called in class A
In code version:
class A:
public class A {
private static ArrayList<ClassToLoad> classesToLoad;
public static void addClassToLoad(ClassToLoad c) {
if (classesToLoad == null)
classesToLoad = new ArrayList<ClassToLoad>();
classesToLoad.add(c);
}
public static void start() {
for (ClassToLoad c : classesToLoad) {
c.onLoad();
}
}
}
class B (and others (C, D etc.) like this one):
public class B {
static {
A.addClassToLoad(new ClassToLoad() {
public void onLoad() {
load();
}
});
}
private static void load() {
// do something here on load ...
}
}
class ClassToLoad:
public interface ClassToLoad {
public void onLoad();
}
This is the same question when you add a new JDBC driver, why you have to call Class.forName() to register a JDBC driver. Every JDBC driver class has a static initializer to register itself with DriverManager. Why? A class loader does not by default load all the classes in jar files. A class is loaded only when it is referenced during execution, which is smart as the class loader never has to load those unused classes into memory. So to resolve your issue, you have to manage to load those classes, like by Class.forName() before you call start(). If you use spring, you can create a list of all those classes in your configure. Spring also provides an util to scan packages for certain types of classes, then you can just specify a package name to scan.
Static fields will be set, and static initializers (static blocks) when ClassLoader will load class for the first time. Rembemer that this will happen when given class will be used for the first time as ClassLoader loads classes in lazy fashion (when needed)
So it seems it's not possible for me to execute those static blocks, so I added every class, which I need to load, into class A, and that way they're actually loading without any problems (in project B). And in project A I need to add other classes, which I need to load, in the main class, obviously.
So I made those classes as Singletons, so they're actually loaded and are ready for "main" loading, launching and disposing. So the adding class looks like this:
A.addClassToLoad(B.getInstance());
I used class ClassToLoad as a generic class to load (sounds funny), though I renamed it to SystemCycle.
So the code as an example of class B now looks like this:
public class B implements SystemCycle {
private static B instance = new B();
private B() {}
public static void getInstance() {
return instance;
}
public void onLoad() { /* some code here */ }
public void onLaunch() { /* some code here */ }
public void onDispose() { /* some code here */ }
}
And SystemCycle class looks now like this:
public interface SystemCycle {
public void onLoad();
public void onLaunch();
public void onDispose();
}
Well, that was obvious, because of example of class B.
And I even made small checking system, so if the user tries to call one of these methods, it will be ignored, as the class implementing SystemCycle checks whether the class A is actually loading, launching or disposing at that moment. But if not, it just can do return. (though if the usermade class doesn't check that, it can be abused by other usermade class).
P.S. addClassToLoad in my project is actually called addSystemToLoad, so I made it here this way to make an example easier to understand.
Small edit: I even tried something to do with annotations first, but even that thing didn't help me.
This question already has an answer here:
Import custom Java class
(1 answer)
Closed 9 years ago.
I am a beginner at java, I used to code in C++ and there when using classes I used to define them in separate files and then include those classes in my main file.
I'm trying to learn threads for socket programming so I can open multiple server ports as threads and accept multiple clients. I know that in Java the file name should be the same as the class name (correct me if i am wrong). This is what I am trying to do:
main.java
include derived.java;
class main1
{
main1()
{
System.out.println("Constructor of main1 class.");
}
void main1_method()
{
System.out.println("method of main 1 class");
}
public static void main(String[] args)
{
main1 my = new main1();
Derived derivedThread = new Derived();
derivedThread.start();
}
}
derived.java
public class derived extends Thread
{
public void run()
{
System.out.println("starting a new thread");
}
}
How can I create a derived class object in main and include it in my main1.java file?
I think I do not fully understand how classes work in Java and what classpath has to be used with it. I have a deadline for my networking project and I am very behind so please help me!
Delete your files and try this, this is how it should look in Java:
Derived class: Derived.java
public class Derived extends Thread {
public void run() {
System.out.println("starting a new thread");
}
}
Main1 class: Main1.java
public class Main1 {
public Main1() {
System.out.println("Constructor of main1 class.");
}
void main1_method() {
System.out.println("method of main 1 class");
}
public static void main(String[] args) {
Main1 my = new Main1();
Derived derivedThread = new Derived();
derivedThread.start();
}
}
Note:
1) Class names are always capitalized, and you are right, the filename must be the same. In addition, the constructor and any calls to the constructor must be capitalized.
2) If you put classes in the same package, you don't need to import them. If you have multiple packages, you would import like so: import packageName.className;. No need for .java at the end, strictly the class name. You can also have nested packages, so you might see things like: import java.util.ArrayList;. This would be using ArrayList class, found in the util package, which is in the java package (built in). You shouldn't have to worry much about making nested packages on smaller projects, but that's the concept.
3) Notice I added the public modifier to Main1 and it's constructor. It is good practice to give a modifier to class names and methods, as well as class variables. See this SO Question for information about modifiers. For a beginner, you should mostly only be concerned with public and private.
I hope that helps, and good luck with your Java studies.
No need to use this include derived.java; .Use import if the derived class exist in different package.The class Derived is different while calling and declaring.
class main1 // Class name must start with Uppercase
{
public static void main(String[] args)
{
main1 my = new main1(); // Can be remove
Derived derivedThread = new Derived();
derivedThread.start();
}
}
public class derived extends Thread // Change derived to Derived
--------------------^
{
public void run()
{
System.out.println("starting a new thread");
}
}
I have remove constructor and one method which is not used.
I thought I reasonably understood the use of packages but am experiencing an ostensibly trivial issue when attempting to use a method from an imported package.
I have three files in the following directory structure:
Tester.java
approach1\Approach.java
approach2\Approach.java
Their code is as follows:
Tester.java
import approach1.Approach;
public class Tester {
public static void main(String[] args)
{
approach1.Approach.sharedMethod("TEXT");
sharedMethod("TEXT");
}
}
approach1\Approach.java
package approach1;
public class Approach {
public static void sharedMethod(String approachText)
{
System.out.println("Approach Text: " + approachText);
}
}
approach2\Approach.java
package approach2;
public class Approach {
public static void sharedMethod(String approachText) { }
}
As you can likely guess, I'm trying to elicit different responses from the different approaches based on what package/class is imported. The problem I encounter is within Tester.java. The first, explicit line works fine whereas the second, imported line (sharedMethod("TEXT")) throws an error of "The method sharedMethod(String) is undefined for the type Tester". I don't understand as I have imported one of the packages, so the method should be visible.
Any clarification would be appreicated as I'm a Java newb. Thanks!
You could import your static method shareMethod like this
import static approach1.Approach.sharedMethod;
the standard kind of imports that you have used only import the classes - so everything within a class must be referenced using the class name. just use:
Approach.sharedMethod()
and now the compiler will be able to know which method to use all depending on which Approach class you have imported at the top.
Just to clarify:
import approach1.Approach;
public class Tester {
public static void main(String[] args)
{
Approach.sharedMethod("TEXT");
}
}
is different from
import approach2.Approach;
public class Tester {
public static void main(String[] args)
{
Approach.sharedMethod("TEXT");
}
}
You should only specify the class name and leave it to the package import statement at the top to determine which package to find the class/methods from.
You only need to explicitly mention the package in the main program body if there is a conflict in names or if you have not imported anything.
I need to load some classes along with their respective static initializations, for example, in a factory method implementation.
If I just make reference to the class using the below syntax, the JVM does not run the static initialization part. Actually, does the JVM even load the classes?
Class<Shape> shapeClass = Shape.class;
or
Shape s = null;
But with class.forname() it does execute static initializations.
Class.forname("Shape");
The question is if this is the only way to do load a java class along with static initializations? Or are there other ways? Any significant performance penalties for using class.forname()?
From Class.forName(String className) API: Invoking this method is equivalent to: Class.forName(className, true, currentLoader).
The second argument = true means initialize class, and initialize class means run static initializers
This is a test to check
package test;
class Test2 {
static {
System.out.println("static init");
}
}
public class Test1 {
public static void main(String[] args) throws Exception {
Class.forName("test.Test2");
}
}
output
static init
but if you load Test2 with
Class.forName("test.Test2", false, ClassLoader.getSystemClassLoader());
there will be no output. You can also use this test to see that Test.class.getName() does not load the class either.
The simplest way to make it load is to add an empty static method and call it:
class Test2 {
public static void load() {
}
...
Test2.load();
When you load/resolve a class, the static initializers are executed in the order they are defined. It shouldn't matter how you load them, reflection or not. That is, unless you're meaning some other sort of initialization?
Im having issues now with static and non staic errors. with sertain variables unable to find the main method.
I have strated the program by creating a seperate file which instantiates the class. like so:
public class StartUp {
public void main(String[] args) {
MainDriver theMainDriver = new MainDriver();
theMainDriver.start();
}
}
Within certain classes in the program it passes variables back to the mainDriver. But when I try to refrence it to, I get the error "cannot find symbol variable theMainDriver" .
e.g:
public void getEmployee() {
theMainDriver.setEmployee(theEmployee);
}
public void getEmployeeID() {
theMainDriver.setEmployeeID( randomIDno);
}
how can I declare the main Driver in a way that makes it more visible to other classes.
It does find the main driver if I do this MainDriver.setEmployeeID( randomIDno); but then it has issues with non static method cannot be referenced from a static context.
You can do the following:
public class StartUp {
public static MainDriver theMainDriver;
public void main(String[] args) {
theMainDriver = new MainDriver();
theMainDriver.start();
}
}
And call from any class as follows:
Startup.theMainDriver.setEmployeeID(randomIDno);
3 things if there was a compilation error.
1) Is MainDriver Public?
2) if MainDriver is in different package, did u import it ?
3) If MainDriver is from diffrent pacakage or different project or a external jar, Did u give that in the classpath ?
also, as the othe guy said, u for got the static part of the main(String[] args)
Firstly, the declaration of main should be like
public static void main(String[] args)
I cant understand how you are running the programm without making it static
Secondly, You didn.t gave the structure of your MainDriver class. May be it is not public. So make your MainDriver class public. I think that will resolve the problem