Timothy Miller
Timothy Miller

Reputation: 1599

Java: How to reference library dependencies *without* 'import' statement?

I'm using NetBeans, and I am factoring out common classes into a library. I want to refer to classes in the library. I can do this easily enough by telling NetBeans that one project is dependent on another, the latter being a Java Library project.

The library project is called "ReVueLib". I have a folder there called "Stream", and in there is a class "StreamClient". The following is an abridged version of what matters:

package Stream;
class StreamClient {
    public void StreamClient() {}
};

I have another project called "ReVueServer", and the main looks like this:

package revueserver;
import Stream.StreamClient;
public class ReVueServer {
    public static void main(String[] args) {
        Class c = StreamClient.class;
        System.out.println(c.getName());
    }
};

Now if I run this, it works fine and prints out "Stream.StreamClient". But say I want to refer to this class without the import. The reason is that in another project, I want to subclass Network.StreamClient as a class called StreamClient. This will help me to avoid refactoring a TON of existing code. In other words, I'm taking advantage of the namespace separation to be able to subclass and reuse the old name.

Unfortunately, if I take out the import, "Stream.StreamClient" doesn't work, nor does "ReVueLib.Stream.StreamClient" or anything else I've tried.

What FQCN do I need to use in order to reference this library class without "import"ing it?

Upvotes: 0

Views: 2490

Answers (5)

Timothy Miller
Timothy Miller

Reputation: 1599

There are lots of good answers that I'll upvote. It turns out that the question is bogus. I had a naming conflict. There was already a Stream class that I had forgotten to remove before trying to add a reference to a Stream namespace. The class name took precedence over the external namespace.

Upvotes: 0

Durandal
Durandal

Reputation: 20069

You cannot refer to a class API without importing it (by either import or explicity fully qualified reference). Ever. Thats set in stone.

I think your misconception is that you could just write "Stream.class" somewhere and depending on whats on the classpath it will work. Thats true only to a very limited extent. While you can replace the Stream.class with another class of the same qualified name and API (that is methods and referenced fields), classes are always referred by their qualified name (thats package + class name).

Your problem sounds more like you need dependency injection with a common API. That allows you to select different implementations of the same API.

This works generally by defining the API, either as an interface or as abstract class:

package my.common;

public interface MyAPI {
    public void doSomething();
}

Your program code can only operate on the defined interface and you will need the interface on the class path to compile and run.

You can then define any number of implementations of the interface anywhere you want:

package my.green;

public GreenAPI implements MyAPI {
    public void doSomething() {
        System.out.println("You reached green API");
    }
}

Finally, you program need to be injected with the information how to get to the implementation at runtime. In the simplest case this can be done by passing the class name as a parameter somewhere, there are also frameworks to do this:

package something;

import my.common.MyAPI;

public MyAPIUser {
    public static void main(String[] args) {
        try {
            Class<?> apiImpl = Class.forName("my.green.GreenAPI");
            MyAPI api = (MyAPI) apiImpl.newInstance();
            api.doSomething();
        } catch (Exception e) {
            e.printStakcTrace();
        }
    }
}

Thats, how the JRE manages to supply a common API for all JDBC drivers by the way.

Upvotes: -1

bszeliga
bszeliga

Reputation: 138

Stream.StreamClient is the FQCN and you should be able to remove the import and use that.

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726987

The proper name of a class in a package includes full name of the package. The import statement lets you avoid writing the prefix, but that is a compile-time trick. That is why your program prints the fully qualified name Stream.StreamClient, even though your program referred to the class by its short name StreamClient.

You can always rewrite your program to use full names for all your classes:

Class c = Stream.StreamClient.class;

or even

java.lang.Class c = Stream.StreamClient.class;

Upvotes: 2

Douglas Held
Douglas Held

Reputation: 1461

I think you need a better explanation than "Doesn't work". Why doesn't this work?

package revueserver;
public class ReVueServer {
    public static void main(String[] args) {
        Class c = Stream.StreamClient.class;
        System.out.println(c.getName());
    }
}

Upvotes: 1

Related Questions