I have a class with an existing import:
import org.packageA.Peeler
public class Potato {
Peeler peeler = new Peeler();
}
I'd like to be able to copy this class or create an object with it but change "import org.packageA.Peeler" to "import org.packZ.Peeler".
Is this possible to do dynamically?
No.
import statements are a bit of a misnomer. import com.foo.A; means: Anytime I write just A in this source file, imagine I wrote com.foo.A and that is all it means. It does not mean: Initialize this class or parse this source file or any other such thing (which is usually what import means in other environments).
Thus, what you're asking is: Can I take class Potato { org.packA.Peeler peeler = new org.packA.Peeler(); } and somehow dynamically create a different Potato class that is as if I wrote class Potato { org.packA.Peeler peeler = new org.packA.Peeler(); } - to which the answer is no; org.packA.Peeler is as related to org.packZ.Peeler as guns and grandmas (i.e.: That they have the same name is immaterial).
Even if you could, what would that mean? Java is statically and nominally typed, it wouldn't be possible to write code that refers to this rewritten potato class without using reflection or dynamic code generation which, in java at any rate, are almost always the wrong answer.
Some exotic options you do have:
Use a regexp or build script plugin to make a source file with some renames applied and include it in the build and compilation process (bad idea, but I guess you can do that)
Use ASM, BCEL or some other classfile tool to create a new class file in byte array form with renames applied, have a custom classloader that dynamically loads this, and then generate bytecode that uses this, or use reflective access. This is extremely convoluted, requires a ton of code, and is almost useless.
Perhaps take a step back and explain the problem you have that made you think: I know! I'll dynamically rewrite this class to use a different package! But I don't know how so I'll ask SO - except you're asking the wrong question, ask about your original problem.
Related
This question already has an answer here:
When is a Java Class loaded?
(1 answer)
Closed 1 year ago.
I need the same code to work on different servers with different libraries.
So for example serverB contains libraryB. ClassB while serverA doesn't.
To make the code work on both servers I do not import the class explicitly but I declare it only when needed. For example:
If(serverB) {
libraryB.ClassB foo = new libraryB. ClassB();
foo.doSomething();
}else{
whatever();
}
This usually works for me but now I installed my code on new servers and I get a NoClassFoundException. I decompile my class and the library is imported. Why? Can I avoid it?
Thanks
Importing some class from a package has nothing to do with trying to locate that class at runtime. Whenever the JVM detects that a class like ClassB is needed, it will try to locate and load that class.
The exact specification when this will happen has some complexities, but it makes no difference whether you wrote the fully qualified libraryB.ClassB or the abbreviated ClassB and an import statement. And locating that class will surely happen before the JVM even tries to execute code that contains a reference to the class (like the code snippet you showed us).
Don't be mislead by the decompilation containing an import statement. You can try for yourself and compare two versions of your code, one written with import, and the other with fully qualified classname. The results will be the same. It's just a convenience of the decompiler preferring short classnames, so it always adds the relevant import statements (as long as that doesn't cause name collisions).
It's hard to understand why code like yours ever ran without throwing that error.
This question already has answers here:
Can a Java class add a method to itself at runtime?
(11 answers)
Closed 2 years ago.
There is a much better question (linked below). My question encouraged bad coding practices without outlining the risks of those practices.
Can a Java class add a method to itself at runtime?
The original question was the following:
Is there a way to add a method to a class definition at runtime?
For example, lets say I had the following interface
public interface Singleton<T> {
#StaticContract
T getInstanceStatic();
}
At runtime, I would scan all classes for methods with the annotation "StaticContract" and add a static version of the implemented method to the class definition. However, I have no idea how I would go about doing this or if this is even possible.
In my current implemention, if runtime reflection doesn't find a static method for a method during initialization, I throw a NoSuchMethodError. The big problem is that the developer might not know that they are supposed to create a static method if they aren't familiar with the interface. Non-static getInstanceStatic() doesn't really make sense with Singletons. It just serves as a reminder to create the static method.
Combined with the ability to recover the erased type using reflection, this would allow me to use generics for far more than they were intended. For example, you would no longer have to define and pass a factory object. You could just define the method in the class that the factory produces.
Also, if there isn't a way to do this during runtime, is there a way to do it during compile time?
What you want is possible!
But not like this. The answer to your actual question is a simple, flat out 'No'. But you don't want what you describe in your question.
Let me elaborate.
Let's first say that you could add methods at runtime. You can't*, but let's say you could.
That would accomplish nothing whatsoever; given:
public class Example implements Singleton<Example> {
#StaticContract Example getInstanceStatic() { return new Example(); }
}
We can already see issues here (this method is.. public. It has to be, that's the rule of interfaces. But given that you want this to be a singleton, that'd be very bad news).
But let's carry on for a moment. The idea is that you want to be able to write, in other code:
Example.instance();
but - how? The compiler won't LET YOU do that, because the method isn't there, and if we go with your plan (of adding the method at runtime), then at compile time it'll never be there, and javac will refuse to compile this. If somehow it DID compile this, then at runtime, where you pull your magic trick and somehow add this method, all would be well, but that's a moot point - short of hacking together a class file with a bytecode editor, there's no way to obtain a class file with the compiled version of Example.instance().
You don't want to add this at runtime.
But maybe you want to add it at compile time.
And THAT? That you can do!
Strategy #1: Lombok
Project Lombok lets you write #UtilityClass which makes it act singleton-esque. Lombok intentionally does not have #Singleton because as a concept, singletons are so universally deriled as bad code style. I guess you could fork lombok and add it if you must have this.
Strategy #2: Annotation Processors
Other than lombok, annotation processors cannot add things to existing source files. But they can make new ones! Given as actual real bytes on disk source file:
#SingletonizeMe
public class Example {
Example() {} // without lombok you're going to have to write this yourself to ensure nobody outside of the package can instantiate this...
}
then you can write an annotation processor which means that javac will automatically produce this file:
// generated code
package same.pkg.as.your.example;
public class ExampleUtil {
public static final Example EXAMPLE_INSTANCE = new Example();
}
and compile it as part of the build, and any code that contains ExampleUtil.EXAMPLE_INSTANCE will just be compiled right along, without any complaints. Annotation Processors solve the problem of 'okay, maybe at runtime this would work but how do I explain to javac to just do what I want without it refusing to compile code that it thinks stands no chance of working at runtime?'.
Strategy #3: Dependency injection systems
From dagger to spring to guice, there are tons of libraries out there that do 'dependency injection', and pretty much all of them have an option to inject things singleton style. Give those 3 libraries a quick look, it should be fairly obvious how that works once you follow their get-started-quick tutorials.
*) You'd think the answer is yes, what with instrumention and the ability to use agent technology to reload a class file. But is that 'adding a method to a class'? No, it is not - it is reloading a class, which does not normally work if you try to add any new members; the hot code replace tech built into VMs doesn't let you change (or add, or remove) any signatures.
I am a novice high school Java programmer and I am having an internal conflict as to which of the following methods is more efficient in Java. If you are importing a single class in Java, is it more efficient to import it as per usual, e.g., import java.util.Scanner; or to use that import statement as part of the Scanner's declaration, as in java.util.Scanner scan = new java.util.Scanner(System.in);.
I know the first is more common and looks nicer, but what if you only need one scanner object? I am sorry if this question is a duplicate; I did not know how to properly word this question in my searches to see if it already existed.
import statements create a compiler-time alias to the symbol imported. That is, it's just a shortcut for typing the full name out - it has no effect on the program while it's running. The compiled code is identical in both cases.
There is no added expense to importing a class, so it makes sense to put all of your imports in the header where anyone looking at your code can easily see what classes are utilized in the program. If you decide later that you want to have more than one scanner object or more than one class from java.util you can use import java.util.* as well.
Pick the more readable of the two. There is no difference in performance, at the end of the day they both get compiled to exactly the same bytecode.
The efficiency lies in how often you might need to write out the package/class/symbol path to the type. If you are certain that you will use it only once, not using an import would work.
But, that is the only upside. There are multiple downsides to avoiding an import statement, including readability, ease of seeing which classes are used in this code file, and extra typing if adding more references becomes necessary. The compiler is completely neutral in all of it, as source either way will compile to the same JVM code.
I know these questions may sound stupid, but in Java, what are Auxiliary classes, how does some one write one, and how does the compiler know that something is an Auxiliary class?
Edit:
The reason I ask this is because the compiler is generating a warning regarding an object in an external library, and I want to know why.
Edit 2:
Here is the compiler warning for those who want it:
warning: auxiliary class Pattern in jregex/Pattern.java should not be accessed from outside its own source file
As descried in Java specification here, you can specify more than one class in one .java file. The class which name matches .java file name will be the main class which can be declared public and be visible to other classes. All other classes in the file therefore are "auxilary" classes. Auxilary class can NOT be declared public and (as #trashgod rightfully pointed out) therefore they only be declared with package-private access. For instance for AClass.java file:
public class AClass {
private AuxilaryClass a;
}
class AuxilaryClass {
private int b;
}
AuxilaryClass class can't be public and is not visible outside this AClass.java file.
However, using auxilary classes considered extremely bad style and against Java Code Convention. Please use separate or inner classes if really needed.
Edit: The term "Auxilary" is not Oracle/Sun official terminology. It has been introduced (or used) here: http://www.youtube.com/watch?v=miTM9rY3He0 and/or here: http://doc.sumy.ua/prog/java/langref/ch05_03.htm
An auxiliary class isn't any kind of official or technical thing as far as I know. Someone might describe a class as auxiliary if it were addressing a secondary concern, or something, but the compiler doesn't have any idea what an auxiliary class is, and neither do I.
In general, if you have error messages from the computer, please paste them in their entirety. If you think the compiler is upset about an auxiliary class, paste the error message: someone else will be able to make sense of it, whereas currently it's being filtered through some kind of confusion that's made you think auxiliary classes are a real thing!
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.