I am currently reading a book on java, and I am currently studying the swing graphical user interface components. While I was doing so, I stumbled upon a code example, where the author was setting an image on a JButton with a very unusual way, depicted below:
Icon bug1 = new ImageIcon( getClass().getResource( "bug1.gif" ) );
In order for the above to work, you need to have the image on the same folder as the .class files. Can someone explain to me why is he using this particular code (which as far as I know, it must be reflection code, but then again, I am not particularly sure about this one) and if there is one way for me to do the same thing, without getting things as complicated as he does?
Things are complicated only if you don't understand them. Once you have understood what the above code does, it will be extremely simple.
getClass() returns the Class object of the current object (this). getResource() called with a relative path as above, looks for a file, in the classpath, named bug1.gif, and in the same package as the Class object being called. So it looks for bug1.gif in the same package as the class containing the above code. getResource() returns a URL. And the ImageIcon constructor takes a URL as argument, loads the image bytes from this URL, and constructs an ImageIcon from these bytes.
So the whole thing just creates an ImageIcon from a file available from the classpath, in the same package as the class calling this code. And this makes sense: you put the images used by a given class in the same package as the class, and you release a jar containing the classes and the images of the application.
You would have figured all this by yourself by reading the javadoc of all these methods.
Java's Swing can get over complicated really fast and I think he's actually using this code for simplicity.
If the image path is relative (the path in your example is), the image has to be located in the same location as the compiled byte code of your program, the .class files. If the image was anywhere else, your program simply couldn't find it.
Relative paths like this are very useful especially when you want to compile your finished project into a JAR file. Your image will be included in the JAR with all your .CLASS files. You will be able to download your compile program, run it, and your images will be right there in your GUI as you would expect.
Class#getResource(String) returns an URL to resource from the classpath. This is a convinient way of loading resources that are stored inside your application JAR file. If the image lies somewhere on the HDD, you can load it using:
new ImageIcon(new File("/path/to/the/image").toURI().toURL());
which creates the File object, and gets it's path as URL (which will look like file:///path/to/the/image).
Or even easier, as ImageIcon has a contructor that takes a fileName:
new ImageIcon("/path/to/the/image");
Related
I want to implement a function that will take package name as input and list all the contents(only files) inside that package.
public List<String> getContents(String packageName) {
...
}
Example input
packageName = com.spring.com.demo
Expexted output
Class1.java
Class2.java
...
What is the best way to accomplish this task?
You're talking about java's 'classloader' system, which is a slight misnomer, in that it can also load resources other than classes. Point is, classes are a resource that are located somewhere, and the JVM itself needs to find them. After all, when you are running your main class and it refers to 'new Foobar()', the jvm needs to find Foobar.class somehow, read the bytes, and turn them into a new class definition.
Java's classloader system is generalized in two ways:
You can call on it to find you stuff.
You can for example write:
MyApp.class.getResource("icons/share.png")
and get a URL object you can pass straight to e.g. ImageIcon. This way, you can ship your icons for your GUI app together with your class files, and it's completely unified: However the system is loading the classes, be it from disk, from inside a jar file, from eclipse's module system if it's an eclipse plugin, or from the network - this way you're loading your images from the same place.
You can make your own
Let's say you want to write a system that loads classes (and other resources, like images) directly from the web. You can do that: You can make your own ClassLoaders.
Now for the crux of the matter
That means ClassLoader is an abstract concept that lists which features it has. It's like any other interface / abstract class in that regard: It's a template that defines what you can do with one, so that anybody can provide you with an implementation of it.
Here's the crucial thing you must understand so that you know why what you want is impossible (and why the commonly called out 'reflections' library is a hack that doesn't universally work):
The ClassLoader abstract simply has no list command.
Hence, listing? Simply not possible. The only command it does have is 'load Resource X', X being some path-like string. That is all it has. The java classloader system is never in need to 'list all classes in a package', not even when there's a star import (which is just a thing javac knows about, at the class file level star imports aren't a thing). The JVM just needs to e.g. load resource '/java/lang/String.class' - hence, the command 'here is a path, please give me the bytes for it' is all that is neccessary.
The solution to have lists anyway
During compilation, the abstractions do support 'list'. After all, the compiler really does just read java files from a directory (which supports 'list all files inside it'), you can't for example tell the compiler 'please compile all .java files in this .jar file). So, at compile time, you can make a list of resources.
So here's the trick: Save that in a text file and ask for the text file during runtime. Then translate each line in the text file to the full resource path and then ask for each of those. Thus, using just the one API call you have available to you at runtime ('load resource at path X'), you can have a list system anyway. It's just that during the compilation/build/packing step you need the tools that compile/build/pack to do some work and make you a text file with the details.
This is called the SPI (Service Provider Interface) system and java itself uses it - it's how JDBC drivers and e.g. charset implementations are found.
You can use this yourself in this three step process:
Define an interface or abstract class that serves as the thing 'providers' will implement/extend. Let's say it is com.ranjan.MyService`.
At the provider end: Write an implementation for it. Let's say it's com.zwitserloot.ServiceImpl.
During compilation, ensure that in the same place the class files end up (e.g. in the jar file for example), there's META-INF/services/com.ranjan.Myservice (a text file). This file contains the fully qualified class name of each 'provider' class: com.zwitserloot.ServiceImpl is what's on the first (and only) line.
At runtime: Use java.util.ServiceLoader and it'll take care of everything.
Your specific use case
From comments it seems like you don't really need to 'list classes', you have a bunch of classes and need to know if they are 'valid', for some definition of 'valid'. You can either just Class.forName them, though this will also initialize them (run its static initializers). Alternatively, you can run YourOwnClass.class.getResource("com.spring.com.demo.Class1.class"), and check that [A] you get an actual resource (and not null, indicating it doesn't exist), and [B] do whatever validation you want to do on this. For example, toss it through bytebuddy or ASM or some other class format editor and check if it can parse it.
Let's say I'm creating a jar file and have an icon in an asset folder to be included in the jar.
So before using, stage.getIcons().add(icon); in my code is there any particular advantage or disadvantage to having the icon as
Image icon = new Image("Assets/Icon.png");
Vs.
Image icon = new Image(getClass().getResourceAsStream("Assets/Icon.png"));
Both seem to work fine, so I'm looking to pinpoint which I should generally gravitate towards and why.
There's a related topic here but it compares loading styles mostly with web applications.
javafx.scene.Image(String) calls validateUrl, which does additional processing of the String value, including checking the current Threads contextClassLoader for the resource.
The advantage of using something like Class#getResourceAsString is you've already made the decisions for the class, which would be (slightly) faster, but also less ambiguous and would probably be easier to diagnose should you have issues (as you control the source mechanism for the image itself) and aren't leaving the decision making up to code that you don't immediately control (and since validateUrl is private static, can't change)
So I learned about the getCodeBase() method today in my programming class and to be honest, I'm really interested in it and how it works in general. All I know is that it finds the directory of where the source code is stored and it is mostly used in applets. But anyone explaining, in detail, how it actually works like the technicalities and such, I would be super grateful! By the way, I started Java 6 months ago. Thanks!
This is what I learned, just to put a little code in here.
cards[0] = getImage( getCodeBase(), "cards_gif/1.gif" );
getCodeBase() in this case, is used to initalize a part of an array to a image.
It returns whatever the codebase was that was specified in the HTML, or its default.
getDocumentBase()
Gets the URL of the document in which this applet is embedded.
For example, suppose an applet is contained within the document:
http://java.sun.com/products/jdk/1.2/index.html
The document base is:
http://java.sun.com/products/jdk/1.2/index.html
getCodeBase()
Gets the base URL. This is the URL of the directory which contains this applet.
I want to delete this post, but can't do it as it's accepted.
i'm wondering about a specific syntax for the "code" attribute that's used with deployjava.
with something like code: applet.class it's fairly obvious that the call is pointing to a file of that name, presumably in the same directory as the file making the call.
sometimes, though, i see something like code: com.domain.applet.
what is that referring to, and where is that file located in the file structure relative to the script that's making that call?
with something like code: applet.class it's fairly obvious that the call is pointing to a file of that name, presumably in the same directory as the file making the call.
What is obvious is not necessarily the case.
The class might come from a jar, and won't be a loose class file in a directory.
The codebase determines the path to search for classes or jars. It defaults to the current directory when not specified.
Lastly, note that the class attribute should be the 'fully qualified class name'1, and that common nomenclature would have it named as EachWordUpperCase - something like GraphApplet.
sometimes, though, i see something like code: com.domain.applet. what is that referring to, and where is that file located in the file structure relative to the script that's making that call?
OK, let's again assume the applet is called com.domain.GraphApplet - that is the fully qualified name of the GraphApplet class, in package com.domain;.
If that were a loose class file, it would need to be in a directory like ${codebase}/com/domain/. Alternately it would need to be located in the /com/domain/ path inside a jar.
Last note on the FQN. It is common for programmers to add .class e.g. com.domain.GraphApplet.class. While tolerated, that is not correct. It should just be com.domain.GraphApplet
I am trying to put a java program into a HTML page and when launch the page nothing shows up.
How do I call this applet, the only thing I have is a JAR file, I didn't write the program. Thanks all!
edit1: Also I kinda got something going but now it says missing code parameter.
You'll need either a CODE attribute or an OBJECT attribute.
From the Oracle guide to embedding APPLETs:
CODE=< appletFile>
This REQUIRED attribute gives the name of the file that contains the applet's compiled Applet subclass. This file is relative to the base URL of the applet. It cannot be absolute. One of CODE or OBJECT must be present. The value appletFile can be of the form classname.class or of the form packagename.classname.class.
OBJECT=< serializedApplet >
This attribute gives the name of the file that contains a serialized representation of an Applet. The Applet will be deserialized. The init() method will not be invoked; but its start() method will. Attributes valid when the original object was serialized are not restored. Any attributes passed to this APPLET instance will be available to the Applet; we advocate very strong restraint in using this feature. An applet should be stopped before it is serialized. One of CODE or OBJECT must be present.
More, and a tutorial here:
http://download.oracle.com/javase/1.4.2/docs/guide/misc/applet.html