Tricky compiler behavior - java

Simple java code snippet. It has three classes. After compiling the code please delete A.class and then execute the code. Code still runs, why its not checking whether the byte code of A exists or not?
class A {
static {
System.out.println("In the class A");
}
public A() {
}
}
class B {
private A a = null;
static {
System.out.println("In the class B");
}
public B() {
a = new A();
}
}
public class ExampleLinkage {
static {
System.out.println("In the class A");
}
public ExampleLinkage(String str) {
}
public static void main(String args[]) {
try {
System.out.println("In the main method of ExampleLinkage");
Class.forName("com.bt.rtti.B");
} catch(Exception e) {
e.printStackTrace();
}
}
}

I would guess that at no point the class A is needed to be loaded, even though there is an instance of it inside B, since you never instantiate an instance of B.
the JVM is very lazy when it load classes. it loads them either when you instantiate an object of that class (at the first time), when you explicitly load a class with Class.forName() or when you otherwise reference the class in a way that requires information from it (try accessing a static member of A from the static initializer of B and see that A will get loaded.

As your not recompiling it, just running the class.

Class A is not used in the code (i.e. in the main method).
At run-time classes are loaded as they are being used. At that time, you would get a ClassNotFoundError. But if you are not using the class, there is not need for it to be there.
Try to make an instance of B (which needs an instance of A), then you will get an error.

Further to Gordon's answer, you are only running the class, and class A is not required, if you called A's constructor or referenced a static field or method in A, then you would get the ClassNotFoundException you are expecting

Related

java class.forClass() vs Class declaration

I have one class Student which is
package org.ahmed;
public class Student {
public Student() {
// TODO Auto-generated constructor stub
System.out.println("Generated constructor");
}
static { // static block
System.out.println("Hello world static");
}
{ // insance block
System.out.println("Hello world non static");
}
}
and then
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("org.ahmed.Student"); // this line causing static block execution in Student class
// Student s; // this line doesn't execute the static block.
}
}
I understand by using Class.forClass() we can dynamically run any
class in runtime. But I have some question in other case regarding
static block.
If I use Class.forClass("org.ahmed.Student") in my main method, then it's
executing the static block of Student. But if I declare Student s in
main method its doesn't execute the static block. I thought
Class.forClass("ClassName") is same as declaring class with a variable
name.
There's a distinction between loading a class (JLS§5.3 and, I think, JLS§5.4) and initializing a class (JLS§5.5). By default, Class.forName does both, although there's an override you can use that lets you control whether to initialize the class.
Just declaring a Student variable doesn't initialize the class. In fact, even referring to Student.class doesn't initialize the class. You must do something to trigger initialization, such as something that uses the new, getstatic, putstatic, or invokestatic bytecode operations with the class (but see the link to §5.5 for details, there are other things that initialize the class).
So for instance, if you gave Student a public field:
public static String foo = "bar";
...and then in Main.main you did:
System.out.println(Student.foo);
...that would trigger initialization of the class.
When you use Class.forName("org.ahmed.Student") you actually force the JVM to load the class and invoke its static blocks. You can read more here.
From javadoc:
Invoking Class.forName(className) method is
equivalent to: Class.forName(className, true, currentLoader), where the second parameter specifies whether or not the class will be initialized.
So if you don't want to initialize the class, just call the method with initialize = false, e.g:
Class.forName("org.ahmed.Student", false, this.getClass().getClassLoader())}
Declaring the class references loads the class to JVM hence static block will be executed. i'm able to see static block execution on
Student s;
Example:
package com.snofty.test;
public class ClassLoading {
public ClassLoading(){
System.out.println("in constructor");
}
static {
System.out.println("in static block");
}
{
System.out.println("in instance block");
}
public static void main(String[] args) {
ClassLoading classLoading;
}
}
Class.forName()
it is used to load the class dynamically by passing the class name
for example
public void loadClass(String className){
Class.forName(className);
}

instance of child class is gives an error

According to java 7 it is mentioned that we can create derived class instance using base class.
but
its not working i am trying to implement this concept
so that i am mention my code over here...
please provide me the solution and solve the problem....
this is the error
class A
{
public void show()
{
System.out.println("A class");
}
}
class B extends A
{
public void display()
{
System.out.println("B class");
}
}
class Demo
{
public static void main(String args[])
{
B obj=new B();
obj.display();
}
}
If obj is of type B, as in your posted code, it can't give you an error, since B contains the method display.
However, based on the error message in your comment - method display() location: variable obj of type A - the actual code is probably:
A obj=new B();
obj.display();
It fails to compile since the compiler determines which methods can be called by the compile time type of obj, which is A. Since A has no display method, you can't call it unless you cast obj to B explicitly:
A obj=new B();
((B)obj).display();
check your file name. make sure that the name of your file is Demo.java... Because when I Compile and run your code, it works. try also to check your java path.

Is there a way to print to the console from a class that does not contain main in Java?

Say we have the class
package myTest;
public class a {
public static void main(String[] args) {
b printToConsole = new b();
}
}
which I cannot modify. I also have the class
package myTest;
public class b {
public static void printThis() {
System.out.println("this is a test");
}
}
which I can modify. I want to call a (which I cannot modify) and somehow print to the console "this is a test". With the current classes, this obviously does not work and I understand why.
Summary:
Is there a way, without modifying a, to call a and have "this is test" to the console? (b can be modified).
You could either call the print statement in the constructor of b
public b() {
System.out.println("this is a test");
}
or from a static initializer
static {
System.out.println("this is a test");
}
(The second will only produce output for the first object created)
Put System.out.println("this is a test"); in the default/no-arg constructor of b:
public class b {
public b() {
System.out.println("this is a test");
}
}
With the current classes, this obviously does not work and I understand why.
Because the printThis method of class b is not called anywhere in class a, so it doesn't get executed. Methods don't run automatically somehow, they have to be called. You'd have to call the method from class a:
b printToConsole = new b();
printToConsole.printThis();
Or you would have to put the content of the printToConsole method in the constructor of class b (class a would not have to be modified then). The constructor is called when a new instance of b is created (the new b(); statement in class a):
public class b {
// Constructor
public b() {
System.out.println("this is a test");
}
}
Yes you can do it in many ways:-
1st way using constructor
class B
{
public B()
{
System.out.println("This is a test");
}
}
2nd way using anonymous block
class B
{
{
System.out.println("This is a test");
}
}
3rd one is by using static block
class B
{
static{
System.out.println("This is a test");
}
}
Actually there is priorities of execution of these block if these are stated in a single class as follow:-
1.Static Block
2.Init Block(Anonymous Block)
3.Constructor
These all 3 blocks execute at runtime with object initialization.
basically compiler copy the init block to the constructor and it is used for share codes between multiple constructors.

Static block fails to execute for self-registering object in Java

This is a bit of a tricky one to explain, but let's say I have two classes A and B. A contains a static list of factory objects that are registered by each object that provides such a factor. In this example B is such a class and provides an imaginary Factory implementation.
Class A:
public class A {
protected static Map<String, Factory> registered = new HashMap<String, Factory>();
protected static register(String name, Factory factory) {
registered.put(name, factory);
}
public A() {
// Do something with the factories we've registered
}
}
Class B:
public class B {
static {
A.register("Foo", new Factory() {
public Object create() {
return new B();
}
});
}
public B() {
// Create a new instance of class B
}
}
In my program for some strange reason the static block within B is never called, so when I start interacting with A no factories have been registered so it can't do what it needs to do.
If I move the creation of each Factory into A directly there is no problem of course. I'm working under the assumption that because there are no clear references to B from any class that the compiler isn't recognising there's a link between A and B so doesn't bother with B at all. Is there anything I can do to work around this? I'd hoped to avoid adding each new factory into A directly as it makes maintenance more difficult than having new factories simply register themselves, but clearly having none of them work at all is even worse; still, I'd like to somehow get it to work as intended if I can.
In case it's relevant, the particular JVM I'm working with is the Android JVM, could this be a side-effect of some optimisation that that that JVM is using?
You can read about class loading in this blog post. The point is that a class won't be loaded until it is referenced. And the static blocks of a class won't be executed until the class is loaded. The rules are
an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
an static method of Class is invoked.
an static field of Class is assigned.
an static field of class is used which is not a constant variable.
if Class is a top level class and an assert statement lexically nested within class is executed.
A solution is to either instantiate B or call a no-op static method (or any of the above).
public class B {
static {
A.register("Foo", new Factory() {
public Object create() {
return new B();
}
});
}
public void static noOp() {}
public B() {
// Create a new instance of class B
}
}
...
B.noOp();
The Oracle JVM spec states this here.

Why doesn't the class containing main have to be public?

I declared the following class
class A { //not public
public static void main(String args[]) {
System.out.println("done");
}
When I compile and run it, it runs fine and prints the output "done". Same behavior even when I declare it as being in a "package a;"
However, if JVM spec mandates that main method should be public since "it can't see main otherwise", shouldn't it apply to the class as well?
If the JVM "can't see" A.main() when it is not declared public, how is it able to see the class A itself.
Is there any explanation for this other than "because the specification says so"?
The JVM has access to every class in the application all the time because one of its responsibilities is enforcing visibility rules. Therefore, one can draw the conclusion that it can ignore visibility rules if need be (e.g. when the user starts the application, the JVM has to find the entry point, which is main()).
In other words, the JVM is not a class accessing this function, so visibility doesn't apply. It is basically the overseer, managing the application from execution to termination.
For reference, see Execution.
When you declare a class private, you're not making it "invisible", and the same goes for your methods. Declaring a method private simply means it's not callable from outside your class. A static public method of a private class is publicly callable.
The reason the JVM can see a non-public class is because it controls visibility, meaning it sees everything and decides what can see/call/access what.
The use of public on a class is different than on a method, but the concept is the same.
On a method, the public keyword means the method can be used outside the class. An example would be:
class A {
public static void do() {
// Do something
}
}
class B {
public static void main(String[] args) {
A.do(); // This works because do() is public and static
}
}
The same concept applies to classes, but in a different way.
Using public on a class means that it can be used outside the current .java file (it will have its own .class file).
Here's an example:
//C.java
class C {
static void do() {
// Do something
}
public static void run() {
A.do(); // Works because A.do() is public and static
B.do(); // Does not work because B is not a public class
}
}
//A.java
public class A {
public static void main(String[] args) {
B.do(); // Works because B is in the same file
do(); // Duh...
}
public static void do() {
// Do something
}
}
class B {
static void do() {
// Do something
}
}

Categories

Resources