0

I am trying to compile a reflection example with the help of a sample taken from book in Eclipse IDE:

public class Reflection_Test {

    public static void main(String[] args) {

        // In both cases below, "ClassNotFoundException" occurs
        Class c1 = Class.forName("java.util.Date");
        Class c2 = Class.forName("Foo");
    }

}

class Foo {
    // ...
}

I copied the line exactly but this is raising two exceptions. I googled other questions and they suggested to use a correct package name. But in my case I am compiling it under default package. What is it missing?

user963241
  • 6,758
  • 19
  • 65
  • 93
  • 1
    Sounds strange. Sure that there aren't any strange classpath problems with your eclipse? Perhaps checking the build path would be an idea, what JDK/JRE is used? – Florian Schaetz Jul 29 '15 at 13:06
  • 1
    Just to be sure, is it the compiler compiling about uncaught exception or are you getting it during runtime? Because if you have copied the code as it is, you wouldnt be able to compile. – Codebender Jul 29 '15 at 13:09
  • Yes, it doesn't compile at all and two exceptions occur for each `forName` call.. – user963241 Jul 29 '15 at 13:12
  • If it doesnt compile, you cannot run it. That means that we got your question wrong - the Exeptions are not thrown, they are declared Exceptions of the ``forName`` function. – f1sh Jul 29 '15 at 13:13
  • @f1sh: These are known as _checked exceptions_ which occur at compile time in Java. – user963241 Jul 29 '15 at 13:15
  • @user963241 yes, true. But you don't deal with them in any way, which is why your code doesnt compile. If you don't know the basics about exceptions, I wouldn't recommend diving into reflection. – f1sh Jul 29 '15 at 13:17
  • @f1sh: It should compile but it doesn't compile for reason. – user963241 Jul 29 '15 at 13:19
  • @user963241 no, it should not. Because as I said, you don't handle the ``ClassNotFoundException`` anywhere. Check what your compile error message tells you. – f1sh Jul 29 '15 at 13:21
  • The compiler error message exactly tells me "Unhandled exception type ClassNotFoundException" on both the lines. – user963241 Jul 29 '15 at 13:22

2 Answers2

1

Using

public class Reflection_Test {

    public static void main(String[] args) {
        try {
          Class c1 = Class.forName("java.util.Date");
          Class c2 = Class.forName("Foo");

          java.util.Date date = (java.util.Date)c1.newInstance();
          Foo foo = (Foo)c2.newInstance();

          foo.bar(date);
        } catch (Throwable te) {
          System.out.println(te);
        } 
    }

}

class Foo {
  public void bar(java.util.Date date) {
    System.out.println("Hello, world! The date is " + date);
  }
}

fixes the compilation errors and

$ javac Reflection_Test.java
$ java Reflection_Test

gives output

Hello, world! The date is Wed Jul 29 15:39:32 CEST 2015

as expected.

The original compilation problem occurred because Class.forName(String className) is declared to throw a ClassNotFoundException and the compile-time checking of exceptions in Java requires you to handle this exception (by either catching it or declaring it in the throws clause of the method) as it is a so-called checked exception.

Note: You probably want a slightly more refined approach to error handling than

catch (Throwable te) {
  ...
}

by catching the specific exception, in particular ClassNotFoundException (but I was lazy and I augmented the example with creating instances, so there would have been also InstantiationException and IllegalAccessException which need to be caught).

godfatherofpolka
  • 1,645
  • 1
  • 11
  • 24
  • What was the point of using `newInstance` if we are just going to do `Foo foo = (Foo)c2.newInstance();`? Why not then just do `Foo foo = new Foo()` at compile time? – user963241 Jul 29 '15 at 15:54
  • @user963241 Here it is just used as a simple example in order to show that things work as they should. In general, techniques as presented here are called reflection and are used, for example, when some class names are not known at compile time (you could use a String variable instead of the literal "Foo"). For more information see http://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful – godfatherofpolka Jul 29 '15 at 15:59
0

The forName method throws the ClassNotFoundException. You need to handle it in your code or the code won't compile.

This could have happened because:

  • you didn't notice a throws ClassNotFoundException in the main method signature
  • they didn't bother sorrounding the block with a try catch block in the sample
  • the sample did not sorround the code with a try catch on purpose to illustrate an ideea, later to reveal the purpose of the block

Running it will indeed throw ClassNotFoundException for the Foo class. This only happens when your Reflection_Test class has declared a package, in which case you will need the fully qualified name of Foo.

Otherwise, if there is no explicit package it will work once you make it compilable as described above.

Laurentiu L.
  • 6,566
  • 1
  • 34
  • 60
  • @user963241 Then just sorround it with try catch or add throws ClassNotFoundException to main and it will run. – Laurentiu L. Jul 29 '15 at 13:28
  • But why does it should throw exception at all? I already have the `Foo` class defined below so this tells me `ClassNotFoundException ` shouldn't occur. – user963241 Jul 29 '15 at 13:29
  • @user963241 You don't understand. It doesn't occur. But it might. That's the point. Anytime you call a method which specifies that it throws an exception ---such as public static Class> forName(String className) throws ClassNotFoundException {...} from Class.java --- it requires that the exception be handled further up the call stack. It's just the Java essentials https://docs.oracle.com/javase/tutorial/essential/exceptions/declaring.html – Laurentiu L. Jul 29 '15 at 13:33
  • Ah, yes I see the point now. I was confused because the book didn't mean that the exception that _might_ occur should be handled. – user963241 Jul 29 '15 at 13:44