Given a class name as a string, how do I get the package name of it at run time ? I do not have the fully qualified name with package name + class name. Simply only the clas
This is most likely an incredibly inefficient, bloated, inconvenient way of doing what you're trying to achieve, and hopefully there's already an out-of-the-box, single way to do it... but it should work.
Basically, scan through every class in the class path, until you find a class where getSimpleName()
matches the class name you have.
I recommend looking at Google Classpath Explorer to help manage the nuts and bolts of doing this.
It could look something like this:
ClassPath classpath = new ClassPathFactory().createFromJVM();
RegExpResourceFilter regExpResourceFilter = new RegExpResourceFilter(".*", ".*\\.class");
String[] resources = classpath.findResources("", regExpResourceFilter);
resources
is an array of Strings like 'com/foo/bar/Baz.class'. You can now simply loop through and find matching entries, and transform them from slashed to dotted, strip out '.class', etc. Just be careful around trying to match inner classes, as they will have a '$' character in them.
Also, as far as I am aware, this will NOT cause those classes to be loaded.
The only way would be to navigate the directories/jars in classpath and an entry with the class name.
Here is some code that almost does what you want. This code is part of a class I have that searches for implementations/factory methods for creating instances of interfaces. Sorry, don't have the time to change this to look for a named class, should be an easy change, and as I mentioned elsewhere you don't need to load the class, just check the name.
public Class<?> locateImplementation(Class<?> type) {
Class<?> c = null;
String[] cp = System.getProperty("java.class.path").split(File.pathSeparator);
for (int i = 0; (c == null) && (i < cp.length); ++i) {
File f = new File(cp[i]);
if (f.exists() && f.canRead()) {
if (isJar(f)) {
try {
c = searchJar(type, new FileInputStream(f));
} catch (Throwable t) {
// Nothing to worry about
}
} else {
c = searchFile(type, f);
}
}
}
return c;
}
private boolean isClass(String path) {
return path.matches(".+\\.class$") && !path.contains("$");
}
private Class<?> searchFile(Class<?> type, File f) {
return searchFile(type, f, f.getPath());
}
private Class<?> searchFile(Class<?> type, File f, String root) {
Class<?> implementation = null;
if (f.isDirectory()) {
File[] files = f.listFiles();
for (int i = 0; i < files.length; i++) {
implementation = searchFile(type, files[i], root);
if (implementation != null) {
break;
}
}
} else if (isClass(f.getPath())) {
String path = f.getPath().substring(root.length() + 1);
Class<?> c = getClass(path);
if ((c != null) && !c.isInterface() &&
type.isAssignableFrom(c)) {
implementation = c;
}
}
return implementation;
}
private Class<?> getClass(String name) {
Class<?> c;
String className = name.replaceAll("[/\\\\]", ".")
.replaceFirst("^\\.", "").replace(".class", "");
try {
c = Class.forName(className);
} catch (Throwable e) {
c = null;
}
return c;
}
private Class<?> searchJar(Class<?> type, InputStream in)
throws Exception {
ZipInputStream zin = new ZipInputStream(in);
Class<?> implementation = null;
ZipEntry ze;
while ((implementation == null)
&& ((ze = zin.getNextEntry()) != null)) {
String name = ze.getName();
if (name.endsWith("class")
&& name.matches("^com.xxx.+")
&& !name.contains("$")) {
try {
Class<?> c = getClass(name);
if ((c != null) && !c.isInterface()
&& type.isAssignableFrom(c)) {
implementation = c;
}
} catch (Throwable t) {
// Nothing to worry about
}
}
}
return implementation;
}
private boolean isJar(File f) {
return f.getPath().endsWith(".jar");
}
final Package[] packages = Package.getPackages();
final String className = "ArrayList";
for (final Package p : packages) {
final String pack = p.getName();
final String tentative = pack + "." + className;
try {
Class.forName(tentative);
} catch (final ClassNotFoundException e) {
continue;
}
System.out.println(pack);
break;
}
One of the simplest solution:
Test.class.toString().replace("class", "").replace(".","/").replace(" ", "")
Call getPackageName() on the class. It returns the fully qualified package name. Also, it is worth mentioning that this is a Java 9 feature.