4

Consider the following scenario:

Let say I have a class A in "src" folder of my project.

class A {

  void foo() {
     B b = new B();
  }

}

Class B is defined in another jar which is included as a dependency in build.gradle

class B extends C {


}

Now, Class C is defined in another jar which will be provided on runtime and not on compile time. Gradle is able to compile Class A without error.

But, when I import Class c in Class A then it gives "class not found".


import other.C; // this line gives error 

class A {

  void foo() {
     B b = new B();
  }

}

Is this the desired behavior of Java compiler to ignore the Class C if it not imported directly?

Also, what happened if use a function in class A using object of B which is in Class C but not overridden in class B.

Abhilekh Singh
  • 2,845
  • 2
  • 18
  • 24
  • Why should the Java compiler bother about class C when you don't use it directly in A? A just needs B and that is available. That B itself depends on something else doesn't matter for A. – Tom Sep 20 '19 at 12:11
  • 1
    How is the jar containing B created? If B extends C then C.jar needs to be a compile dependency of this jar and should become a dependency of every project using B. – dpr Sep 20 '19 at 12:24
  • @dpr Yes, B.jar will have a dependency on C.jar but my question if it is not provided when we are compiling class A then what happened. – Abhilekh Singh Sep 20 '19 at 15:10
  • @Tom is there some reference you can provide to validate your comment. I'm also assuming that should be the case but I'm not fully sure of it and didn't find any reference regarding it. Also, what happened if use a function in class A using object of B which is in Class C but not overridden in class B. – Abhilekh Singh Sep 20 '19 at 15:14
  • In order to get an answer you should add the gradle files to your question. It very much depends on how the dependencies are specified both for project A and B. – dpr Sep 22 '19 at 13:34
  • you say Now, Class C is defined in another jar which will be provided on runtime and not on compile time. But the compiler should know if C has a constructor if you want to initialize it. – AndreaTaroni86 Sep 26 '19 at 16:30
  • @AndreaTaroni86 You are saying if I create an object of B with default constructor which will call its superclass constructor of C then the compiler should know about C. This is exactly what's not happening and the compiler doesn't report an error even C class is not provided at compile time. Is there any defined rules at what level Java Compiler stops the parsing of classes. – Abhilekh Singh Sep 27 '19 at 04:53

2 Answers2

0

The exact answer to your question depends on the Java compiler version and whether or not it requires access to C for doing its job.

All in all, I would say that such a setup is fragile and you should not do it. If your library that defines A requires B which effectively makes use of C in its public API as is the case for extends then C should be made visible to your library.

Louis Jacomet
  • 13,661
  • 2
  • 34
  • 43
0

First of all we need to understand how java compilers work. Whatever you reference by name or as a 'token' in your code, should be accessible to compiler during compilation phase.

The classes that you load using Class.forload or getClass method are not required to be available in the classpath.

What you are essentially referring by compiletime and runtime is about packaging.

What you say that a particular dependency say Class C will be provided at runtime, its an instruction to bundle tasks to ignore that dependency while building the jar. So if you compile and deploy your application as jar, class C will not be present in it. At the same time, the jar containing class B will be included in your deployment package.

If you provide exact gradle file, I might be able to answer more precise.

Anand Vaidya
  • 1,374
  • 11
  • 26