I would like to be able to do something like (psuedo-code):
if (classAvailable) {
// do a thing
} else {
// do a different thing
}
What would be even better is if I could extend a class from ClassA if it's available or ClassB, if it isn't. I suspect this isn't possible though.
You can do the first part:
try {
Class.forName("my.ClassName");
// It is available
}
catch (ClassNotFoundException exception) {
// It is not available
}
My usual approach to this is:
Separate out the code which uses the optional library into a different source directory. It should implement interfaces and generally depend upon the main source directory.
In order to enforce dependencies in the build, compile the main source directory without the optional library, and then the source that depends on the optional library (with other class file from other source directory and the library on the compiler classpath).
The main source should attempt to load a single root class in the optional source directory dynamically (Class.forName, asSubclass, getConstructor, newInstance). The root class' static intialiser should check that the library is really available and throw an exception if it is not. If the root class fails to load, then possibly follow the Null Object pattern.
I don't think there's a way to dynamically choose whether to extend one class or another, except if you made a program that can manipulate bytecode directly (simple example: hold the compiled bytecode for both versions of the subclass as strings, and just use a ClassLoader to load whichever one corresponds to the superclass you have available).
You could do it in Python, though ;-)
In case you are using Spring, try to use org.springframework.util.ClassUtils#isPresent
Related
Is it possible to detect type of instance with checkstyle?
For instance, I have code block like
class A {
...
private void method test() {
....
throw new MyCustomException("Some message");
}
}
In this case I want to get real instance of MyCustomException.
I know that we can use TokenTypes.LITERAL_NEW in custom plugin, but in this case I can get only name for an exception, but not instance type (I don't have an address for this exception type).
Since what you want is the classpath of the exception, you must emulate how Java determines the classpath from the source code.
This requires you examining the imports and package. You won't be able to fully determine this with Checkstyle since it only looks at a single file and Java actually looks at multiple folder locations, but you can get pretty close.
First look for an import with that exact class name. If there is no import, then the choices are it is coming from the java.lang package or the current package of the file being examined. You should build a list for any java.lang exceptions (if any) that you want to auto-identify. Anything else in that list would default to the file's package declaration.
There are a few checks in Checkstyle that implement this logic if you wish to see examples.
Let's say I wanted to assert that a given Java source folder contained all of the source code required to run any of the programs contained in the source folder. Simply showing that the whole source folder compiles would be insufficient because perhaps some of those programs use reflection to instantiate objects. As such I could search through all the code and look for invocations of newInstance() to learn what classes are expected to be present at runtime. But what about calls to Class.forName(...) that are not involved in calls to newInstance() ? Better check for those as well. But how many such things do I need to check for?
Is there any sort of exhaustive list I could consult to ensure that I am considering each way in Java that such a runtime dependency could be introduced? Restated, does there exist some list of operations such that if I can show none of the source in a source folder use those operations (and that folder compiles) that all (code) dependencies are present?
If no such list exists, could we start one in this thread and make a best effort to cover all operations that we know of?
Edit
I'd like to narrow the question a little. What I'm most interested in showing is that if a codebase compiles, all dependencies are present. It seems to me to do this I would need to first compile the codebase and then check to see if any of the code ever calls certain methods (e.g. newInstance) that could introduce a runtime dependency. If no such methods are found, I'm reasonably sure that all required code is present in source form and running the program will not generate a ClassNotFoundException.
Answer to the original question
There is no extensive way You can do this as far as I know. I mean consider the following code:
public static Object calleableFromAnywhere(Object o) throws IllegalAccessException, InstantiationException {
Object ret = null;
if(!Objects.isNull(o)){
ret = o.getClass().newInstance();
}
return ret;
}
In this case You do not even know what kind of dependency You will have at runtime.
If you restrict your search to constructor based object creation only you have a lot of choices also:
Constructor<?> constructor = o.getClass().getConstructor();
//there could be a lot of constructors enclosing different paramethers
Object something = o.getClass().newInstance();
//default constructor called
And even those could be obtained by reflection... The rabbit hole is infinitely deep.
The call You mentioned Class.forName(...) could take any parameter String and those could be given from a database or an input field from the user.
I do not think it is possible to predict all the String variables you could encounter at runtime. If you have anything like this You are not likely to succeed.
TL.DR.: there is no exact solution I know of. According to the question You are not only interested in newInstance or instance creations as you could have static methods on classes as dependency as well. The idea is nice, but there is no 100% solution to this problem.
Narrowed/clarified questions answer
The a newInstance call is not introducing a new dependency. It could be called on a loaded class definition only. (Basically you never get to the newInstance if the class could not be loaded.) So if your goal is to answer with high certainty that if a class will not be represented is an another problem.
Altering the previous example shows that you are not likely to have the definit dependent classes:
public static Class getClass(String name) throws ClassNotFoundException {
return Class.forName(name);
}
As name could be anything that you can recieve runtime. Also there is an other ways to load classes as the following example shows.
public Class getClassExample1(String name) throws ClassNotFoundException {
return this.getClass().getClassLoader().loadClass(name);
}
According to the JavaDoc of ClassNotFoundException exception these places are using it:
#see java.lang.Class#forName(java.lang.String)
#see java.lang.ClassLoader#findSystemClass(java.lang.String)
#see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
Those are the places where it is thrown, but you have to check every path to those methods like someInstance.getClass(name).
In addition to runtime dependencies You can encounter NoClassDefFoundError as well. If you are using some containers and set some dependencies as provided for example in maven You can also have some problems runtime, while the compilation was totally fine.
TL.DR.V2: You can only minimize the risk of not having a dependency with a static analysis, but if you want to try it you should check the mentioned methods and all of the call chains (even via reflection) that could lead to these.
Not generally possible
You can, of course, answer this question for trivial cases, but not universally. Its not possible to tell for the general case if the code will ever attempt to load a class not available.
Think of any code that takes input from any external source and loads a class in response (e.g. user input is a JDBC database url, requiring a JDBC driver). Same goes for cases where a class may be resolved in response to internal program state, but the state isn't trivially predictable.
TLDR:
Because its the same as solving the halting problem
Actually something like Annotation Processing would add extra complexity to the problem, you can generate Java code with it at compile time, which can have dependencies you don't see directly in code and would need further understanding of the subject and its limitations on making new dependencies, you can read more about it here: AnnotationProcessing 101
Is there a way to obtain the Java source code from a class name?
For example, if I have access to the library with the class java.io.File, I want its source code.
I am working on a kind of parser and I need the source at execution time. I have also to search it recursively.
Say the aforementioned class has this method:
int method (User user) {...}
I would need to obtain User's source code, and so on and so forth with its inner classes.
Is there any way to obtain the java source from a class name? For example:...
You may want one of several possible solutions. Without knowing what you really want to do with the information, we can't be very precise with our recommendations, but I'd start by steering you away from source code if possible. JSE source code is available online, as are many open source libraries, but that may not always be the case. Additionally, you'll need to keep it all organized when you want to find it, much like a classpath, whereas the Class objects are much easier to get hold of, and manipulate, without having to parse text again.
Reflection
If you just need information about a class at runtime, just use the Java Reflection API. With it, given a Class object you can, for example, get the types of a specific field, list all fields and iterate over them, etc...:
Class clazz = User.class;
Field field = clazz.getDeclaredField("var");
System.out.println(field.getType().getName());
Reflection is useful for discovering information about the classes in the program, and of course you can walk the entire tree without having to find source code, or parse anything.
Remember you can lookup a class object (as long as it's on the classpath at runtime) with Class.forName("MyClass") and reflect on the resulting Class.
Bytecode Manipulation
If you need more than information, and actually want to manipulate the classes, you want bytecode manipulation. Some have tried to generate source code, compile to bytecode and load into their program, but trust me - using a solid bytecode manipulation API is far, far easier. I recommend ASM.
With it, you can not only get information about a class, but add new fields, new methods, create new classes... even load multiple variations of a class if you're feeling self-abusive. An example of using ASM can be found here.
Decompilation
If you really, really do need the source, and don't have it available, you can decompile it from a class object using one of the various decompilers out there. They use the same information and techniques as the above two, but go further and [attempt] to generate source code. Note that it doesn't always work. I recommend Jode, but a decent list, and comparison of others is available online.
File Lookup
If you have the source and really just want to look it up, maybe all you need is to put the .java files somewhere in a big tree, and retrieve based on package name as needed.
Class clazz = User.class;
String path = clazz.getPackage().getName().replaceAll("\\.","/");
File sourceFile = new File(path, clazz.getName() + ".java")
You want more logic there to check the class type, since obviously primatives don't have class definitions, and you want to handle array types differently.
You can lookup a class by name (if the .class files are on your classpath) with Class.forName("MyClass").
You can get a good approximation of the source from a class file using the JAVA decompiler of your choice. However, if you're really after the source of java.io.File then you can download that.
The best and simplest bet can be javap
hello.java
public class hello
{
public static void main(String[] args)
{
System.out.println("hello world!");
world();
}
static public void world()
{
System.out.println("I am second method");
}
}
do a javap hello and you will get this:
Compiled from "hello.java"
public class hello extends java.lang.Object{
public hello();
public static void main(java.lang.String[]);
public static void world();
}
Yes, if you download the source code. It's available for public download on the official download page.
If you're using Eclipse whenever you use the class you could right click > View Source (or simply click the class > F3) and it'll open a new tab with the source.
You can print the resource path from where the class was loaded with
URL sourceURL=obj.getClass().getProtectionDomain().getCodeSource().getLocation();
It will be a .class file , .jar,.zip, or something else.
So what you're trying to do is get the Java class at execution. For this, you need Java reflections.
If your goal is to get information about what's in a class, you may find the Java reflection API to be an easier approach. You can use reflection to look up the fields, methods, constructors, inheritance hierarchy, etc. of a class at runtime, without needing to have the source code for the class available.
Is there any way to obtain the java source from a class name?
The answer is complicated, not least because of the vagueness of your question. (Example notwithstanding).
In general it is not possible to get the real, actual Java source code for a class.
If you have (for example) a ZIP or JAR file containing the source code for the classes, then it is simple to extract the relevant source file based on the classes fully qualified name. But you have to have gotten those ZIP / JAR files from somewhere in the first place.
If you are only interested in method signatures, attribute names and types and so on, then much of this information is available at runtime using the Java reflection APIs. However, it depends on whether the classes were compiled with debug information (see the -g option to the javac compiler) how much will be available. And this is nowhere like the information that you can get from the real source code.
A decompiler may be able to generate compilable source code for a class from the bytecode files. But the decompiled code will look nothing like the original source code.
I guess, if you have a URL for a website populated with the javadocs for the classes, you could go from a class name, method name, or public attribute name to the corresponding javadoc URL at runtime. You could possibly even "screen scrape" the descriptions out of the javadocs. But once again, this is not the real source code.
I'm writing a library that needs to have some code if a particular library is included. Since this code is scattered all around the project, it would be nice if users didn't have to comment/uncomment everything themselves.
In C, this would be easy enough with a #define in a header, and then code blocks surrounded with #ifdefs. Of course, Java doesn't have the C preprocessor...
To clarify - several external libraries will be distributed with mine. I do not want to have to include them all to minimize my executable size. If a developer does include a library, I need to be able to use it, and if not, then it can just be ignored.
What is the best way to do this in Java?
There's no way to do what you want from within Java. You could preprocess the Java source files, but that's outside the scope of Java.
Can you not abstract the differences and then vary the implementation?
Based on your clarification, it sounds like you might be able to create a factory method that will return either an object from one of the external libraries or a "stub" class whose functions will do what you would have done in the "not-available" conditional code.
As other have said, there is no such thing as #define/#ifdef in Java. But regarding your problem of having optional external libraries, which you would use, if present, and not use if not, using proxy classes might be an option (if the library interfaces aren't too big).
I had to do this once for the Mac OS X specific extensions for AWT/Swing (found in com.apple.eawt.*). The classes are, of course, only on the class-path if the application is running on Mac OS. To be able to use them but still allow the same app to be used on other platforms, I wrote simple proxy classes, which just offered the same methods as the original EAWT classes. Internally, the proxies used some reflection to determine if the real classes were on the class-path and would pass through all method calls. By using the java.lang.reflect.Proxy class, you can even create and pass around objects of a type defined in the external library, without having it available at compile time.
For example, the proxy for com.apple.eawt.ApplicationListener looked like this:
public class ApplicationListener {
private static Class<?> nativeClass;
static Class<?> getNativeClass() {
try {
if (ApplicationListener.nativeClass == null) {
ApplicationListener.nativeClass = Class.forName("com.apple.eawt.ApplicationListener");
}
return ApplicationListener.nativeClass;
} catch (ClassNotFoundException ex) {
throw new RuntimeException("This system does not support the Apple EAWT!", ex);
}
}
private Object nativeObject;
public ApplicationListener() {
Class<?> nativeClass = ApplicationListener.getNativeClass();
this.nativeObject = Proxy.newProxyInstance(nativeClass.getClassLoader(), new Class<?>[] {
nativeClass
}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
ApplicationEvent event = new ApplicationEvent(args[0]);
if (methodName.equals("handleReOpenApplication")) {
ApplicationListener.this.handleReOpenApplication(event);
} else if (methodName.equals("handleQuit")) {
ApplicationListener.this.handleQuit(event);
} else if (methodName.equals("handlePrintFile")) {
ApplicationListener.this.handlePrintFile(event);
} else if (methodName.equals("handlePreferences")) {
ApplicationListener.this.handlePreferences(event);
} else if (methodName.equals("handleOpenFile")) {
ApplicationListener.this.handleOpenFile(event);
} else if (methodName.equals("handleOpenApplication")) {
ApplicationListener.this.handleOpenApplication(event);
} else if (methodName.equals("handleAbout")) {
ApplicationListener.this.handleAbout(event);
}
return null;
}
});
}
Object getNativeObject() {
return this.nativeObject;
}
// followed by abstract definitions of all handle...(ApplicationEvent) methods
}
All this only makes sense, if you need just a few classes from an external library, because you have to do everything via reflection at runtime. For larger libraries, you probably would need some way to automate the generation of the proxies. But then, if you really are that dependent on a large external library, you should just require it at compile time.
Comment by Peter Lawrey: (Sorry to edit, its very hard to put code into a comment)
The follow example is generic by method so you don't need to know all the methods involved. You can also make this generic by class so you only need one InvocationHandler class coded to cover all cases.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
ApplicationEvent event = new ApplicationEvent(args[0]);
Method method = ApplicationListener.class.getMethod(methodName, ApplicationEvent.class);
return method.invoke(ApplicationListener.this, event);
}
In Java one could use a variety of approaches to achieve the same result:
Dependency Injection
Annotations
Reflection
The Java way is to put behaviour that varies into a set of separate classes abstracted through an interface, then plug the required class at run time. See also:
Factory pattern
Builder pattern
Strategy pattern
Well, Java syntax is close enough to C that you could simply use the C preprocessor, which is usually shipped as a separate executable.
But Java isn't really about doing things at compile time anyway. The way I've handled similar situations before is with reflection. In your case, since your calls to the possibly-non-present library are scattered throughout the code, I would make a wrapper class, replace all the calls to the library with calls to the wrapper class, and then use reflection inside the wrapper class to invoke on the library if it is present.
Use a constant:
This week we create some constants
that have all of the benefits of using
the C preprocessor's facilities to
define compile-time constants and
conditionally compiled code.
Java has gotten rid of the entire
notion of a textual preprocessor (if
you take Java as a "descendent" of
C/C++). We can, however, get the best
benefits of at least some of the C
preprocessor's features in Java:
constants and conditional compilation.
I don't believe that there really is such a thing. Most true Java users will tell you that this is a Good Thing, and that relying on conditional compilation should be avoided at almost all costs.
I'm don't really agree with them...
You CAN use constants that can be defined from the compile line, and that will have some of the effect, but not really all. (For example, you can't have things that don't compile, but you still want, inside #if 0... (and no, comments don't always solve that problem, because nesting comments can be tricky...)).
I think that most people will tell you to use some form of inheritance to do this, but that can be very ugly as well, with lots of repeated code...
That said, you CAN always just set up your IDE to throw your java through the pre-processor before sending it to javac...
"to minimize my executable size"
What do you mean by "executable size"?
If you mean the amount of code loaded at runtime, then you can conditionally load classes through the classloader. So you distribute your alternative code no matter what, but it's only actually loaded if the library that it stands in for is missing. You can use an Adapter (or similar) to encapsulate the API, to make sure that almost all of your code is exactly the same either way, and one of two wrapper classes is loaded according to your case. The Java security SPI might give you some ideas how this can be structured and implemented.
If you mean the size of your .jar file, then you can do the above, but tell your developers how to strip the unnecessary classes out of the jar, in the case where they know they aren't going to be needed.
I have one more best way to say.
What you need is a final variable.
public static final boolean LibraryIncluded= false; //or true - manually set this
Then inside the code say as
if(LibraryIncluded){
//do what you want to do if library is included
}
else
{
//do if you want anything to do if the library is not included
}
This will work as #ifdef. Any one of the blocks will be present in the executable code. Other will be eliminated in the compile time itself
Use properties to do this kind of thing.
Use things like Class.forName to identify the class.
Do not use if-statements when you can trivially translate a property directly to a class.
Depending on what you are doing (not quite enough information) you could do something like this:
interface Foo
{
void foo();
}
class FakeFoo
implements Foo
{
public void foo()
{
// do nothing
}
}
class RealFoo
{
public void foo()
{
// do something
}
}
and then provide a class to abstract the instantiation:
class FooFactory
{
public static Foo makeFoo()
{
final String name;
final FooClass fooClass;
final Foo foo;
name = System.getProperty("foo.class");
fooClass = Class.forName(name);
foo = (Foo)fooClass.newInstance();
return (foo);
}
}
Then run java with -Dfoo.name=RealFoo|FakeFoo
Ignored the exception handling in the makeFoo method and you can do it other ways... but the idea is the same.
That way you compile both versions of the Foo subclasses and let the developer choose at runtime which they wish to use.
I see you specifying two mutually exclusive problems here (or, more likely, you have chosen one and I'm just not understanding which choice you've made).
You have to make a choice: Are you shipping two versions of your source code (one if the library exists, and one if it does not), or are you shipping a single version and expecting it to work with the library if the library exists.
If you want a single version to detect the library's existence and use it if available, then you MUST have all the code to access it in your distributed code--you cannot trim it out. Since you are equating your problem with using a #define, I assumed this was not your goal--you want to ship 2 versions (The only way #define can work)
So, with 2 versions you can define a libraryInterface. This can either be an object that wraps your library and forwards all the calls to the library for you or an interface--in either case this object MUST exist at compile time for both modes.
public LibraryInterface getLibrary()
{
if(LIBRARY_EXISTS) // final boolean
{
// Instantiate your wrapper class or reflectively create an instance
return library;
}
return null;
}
Now, when you want to USE your library (cases where you would have had a #ifdef in C) you have this:
if(LIBRARY_EXISTS)
library.doFunc()
Library is an interface that exists in both cases. Since it's always protected by LIBRARY_EXISTS, it will compile out (should never even load into your class loader--but that's implementation dependent).
If your library is a pre-packaged library provided by a 3rd party, you may have to make Library a wrapper class that forwards it's calls to your library. Since your library wrapper is never instantiated if LIBRARY_EXISTS is false, it shouldn't even be loaded at runtime (Heck, it shouldn't even be compiled in if the JVM is smart enough since it's always protected by a final constant.) but remember that the wrapper MUST be available at compile time in both cases.
If it helps have a look at j2me polish or Using preprocessor directives in BlackBerry JDE plugin for eclipse?
this is for mobiles app but this can be reused no ?
I have a Java assignment that uses components to build program. The teacher gave us a JAR we are to use to build the calculator using Eclipse. The JAR has 2 classes. We must import the JAR and use its classes.
I import the JAR:
import SWEB401_HW1.NumericOperation;
but when I try to create an object for the class, it gives me an error because the constructor is not visible. What can I do to use the class "NumericOperation" to build the calculator?
With the information you provided - and considering that this is an assignment - I can only give you a few hints about what to look for.
Assuming your project is set up correctly, and you still cannot create instances of NumericOperation, ...
... there could be static factory methods in NumericOperation.
... the "other class" could act as factory for NumericOperation instances
... NumericOperation could actually be an interface or abstract class that you need to implement
EDIT:
Don't want to give it all away, so I'll keep this vague. As NumericOperation indeed seems to be an abstract class, try writing a class like the following and see what you must do to stop the IDE complaining:
public class MyNumericOperation extends NumericOperation {}
You can also have a look at the inheritance part of the Java Tutorial here.
If the constructor is not visible, then you are trying to invoke a non-public constructor. Look at the code or java doc for your NumericOperation class and find a constructor that is public. Most likely you're invoking the no-argument constructor and the class has specifically hidden it because you need an initial value.
For instance:
public class MyClass {
private MyClass() {
// Don't let callers instantiate me without args!
}
public MyClass(int initialValue) {
// create a new object with initialValue
}
}
If calling code attempts this:
MyClass obj = new MyClass();
You'll get the error you've posted. You need to call new MyClass(int) instead.
If the error you get is saying that the onstructor is not "visible", then it's talking about visibility in java (public, provate, protected and package).
This is good - it means that you have sucessfuly imported the class and that it's on your classpath. Ignore all the other answers that talk about fooling with your classpath - eclipse is taking care of it for you ok.
At a guess, your teacher f*cked up has not put a "public" declaration on the constructor you need to use.
To fix this, your class that you are writing needs to be in the SWEB401_HW1 package.
The easiest way in eclipse to do this is to right-click the java file in the navigator and to "refactor" it by "moving" it into package SWEB401_HW1.
If I understand your question correctly, you do not need to import anything. That's not how you access classes in a JAR file. Instead you need to add the path of the JAR file to Java's classpath; how exactly you do that depends on your operating system. Alternatively, you could extract the JAR file into the directory where your own program's class file is. A JAR file is just a ZIP file with a different extension, so you can extract it using whatever you normally use to open ZIP files, or you can use the jar tool included with the JDK:
jar xf SWEB301_HW1.jar
There's no need to extract anything. You need to use the JAR in your project by adding it to the classpath.
Are you using Eclipse? If so, you can go to the project properties -> java build path -> libraries -> add external JARs -> search for your jars and add them.
That way you'll get all the JAR classes in your project.
If the instructor gave you Javadocs, an API listing, or the source look for things like this:
public static NumericOperation ()
public NumericOperation()
public NumericOperation ()
The first one could be in any class, but would likely be in the NumericOperation class.
The second one would be a constructor in the NumericOperation class that takes parameters. Remember that if the class provides a constructor the compiler does not generate an no-argument one for you.
The last one would be in another class (since you need an instance to call the method).
In the future posting the exact error message that the compiler spit out is more helpful than an rough statement of what it said.
In agreement with some earlier answers, you need to have the jar available via the classpath, so when you run or compile do
java(c) -cp myjar.jar:. etc
I usually include the current directory so that it doesn't forget that my code is in the path.
When you import, you must use the java package names. Open the jar in a zip program and file the path to the class files you need, then put "import path;" where you replace the folder separators by '.'