I need to check if a class exists in a package.
I know I can use Class.forName to check if a class exists, but how do I verify if it is inside a specific package?
Do not use Class.forName for this.
Class.forName takes a fully qualified name. Fully qualified names include the package, but also the outer classes, and therefore, aren't going to work here:
package pkg;
class Outer {
class Inner {}
}
results in the fully qualified name, the name you'd have to pass to CFN, for Inner is: Class.forName("pkg.Outer.Inner"); - and how do you tell Outer is an outer class and not part of the package name?
Java does not have hierarchical packages; there is no relationship between pkg and pkg.subpkg, so your question hopefully does not involve 'how do I check if the package part starts with a certain string', as you shouldn't be asking that question in the java ecosystem.
Thus, let's move away from Class.forName.
Note that the class needs to be available at runtime, or it won't work. "Fortunately", if the class is not available at runtime and you want to determine the package given e.g. a fully qualified class name, because of the above issue with outer and inner classes, that job is literally impossible, so if that's what your question boiled down to, you can stop reading: No can do. Let's assume it is available at runtime.
You need a Class<?> object.
Each class is represented by an object, of the java.lang.Class<?> type. You need to obtain such an object and then you can determine which package it is in.
Strategy 1: Class.forName
Class.forName("pkg.Outer.Inner") will get you the Class<?> object and from there you can ask it what its package is, and that would get you pkg, which you presumably want to know. So that's one way: Given a string representing the fully qualified name of a class, toss it through Class.forName, and then operate on the Class object you get out of this.
Strategy 2: Class literals.
Java has special syntax to obtain the Class<?> object given a type reference. So, if you know the type reference when you write your code, you can use this:
package pkg;
class Outer {
class Inner{}
private static Class<?> innerClassObj = Inner.class;
}
However, if you can write it that way, you already know from which package that class is coming from at write time, so that makes your question entirely moot. Why try to figure out at runtime what you already know?
Just in case this is what you wanted to know: Check your imports, and in any major IDE, hold CMD (CTRL on non-macs), and click on the name, it'll take you to where it is defined, and the package will be listed right there. Or just float over it, that works in most IDEs just as well.
Strategy 3: From an object instance.
All objects have a .getClass() method which obtains the Class<?> instance representing how the object was created.
Careful though!
List<String> list = new ArrayList<String>() {
#Override public boolean add (String other) {
log.info("Added: {}", other);
return super.add(other);
}
};
This is perfectly valid, somewhat common and completely innocent java code. However, it means that now invoking list.getClass() and then asking for the name of that class gives you something like com.foo.internal.WhateverClassThatCodeShowedUpIn$1, because that is technically a subclass, and thus list is an instance of that. If you wanted to check if the object is 'of a class that is from the java.util package', then just looking at list.getClass() would incorrectly tell you it is not.
The fix is to be aware of this and to always (in a while loop) go through all the superclasses. list.getClass().getSuperclass() would resolve to the exact same instance as java.util.ArrayList.class would, invoking getSuperclass on that will get you to java.util.AbstractList.class, and from there, java.lang.Object.class and then null. java.util.List.class never shows up here - that is not a class, that is an interface. If you want those too - well, .getInterfaces() exists.
So, if you want to know: Is this object compatible with some class that is in some specific package - there is your answer. Only way is to use while loops (and if you want to check interfaces, a queue or recursive method even).
Strategy 4: Have it be given to you.
You can always just have a method that takes in a Class<?> as a parameter. Various APIs out there give you one, as well.
Okay, I have a Class<?> instance, now what?
You could call the .getPackage() method on it, but unfortunately the JVM spec dictates that this doesn't actually have to return something (it may return null). So that's not a great solution. Instead, I suggest you invoke .getName() on it, and then go to town on the string you get.
That string you get would be pkg.Outer$Inner. You can see how you can derive the package from this:
Find the last ..
If it exists, strip that and all after it.
If there is no dot at all, it's in the unnamed package.
Voila. That'll leave you with pkg.
NB: Take into account the bit written about in strategy 3: For your needs you may have to scan through the superclass and all superinterfaces, recursively.
Related
First, please take a look at the following code.
package test;
class c_hi {
public static void method_hi(){
System.out.println("hi");
}
}
class c_bye {
public void method_hi(){
System.out.println("bye");
}
}
public class test {
public static void main(String[] args){
c_hi.method_hi();
c_bye c_hi = new c_bye();
c_hi.method_hi();
}
}
I've been using Java for several years, and I understand the general rules for naming class names and variable names.
However, I got a very interesting question. If the name of the reference variable of the "c_bye" class is "c_hi" (a class named "c_hi" already exists),
I can't access "method_hi" of class "c_hi" from inside class "test".
Of course, I know that this problem can be prevented or circumvented by not overlapping class names and variable names, package separation, and FQCN etc.
Apart from the usual way of avoiding duplicate names, is there a more grammatical way to solve this problem? Please tell me your opinion. (Or, I would appreciate any documentation, links, or other questions on Stack Overflow that I can refer to.)
This code works the same for both JDK versions 8 and 15.
This should "fix" the problem:
test.c_hi.method_hi(); // Using the fully qualified class name.
However, the correct solution would be:
Don't ignore Java style rules. The rules say Java method name should start with a lowercase letter, and a class name should start with an uppercase letter.
Avoid using the same name for a static method and an instance method.
(You actually can't do this in some cases. For example, if c_bye extends c_hi then you get a compilation error about an instance method not being allowed to override a static method.)
Don't attempt to call a static method using an instance variable. Use the class name. (Which cannot be confused with a variable name if you follow the style rules!)
It is legal Java to do that, but it tends to fool the reader into thinking that the method is an instance method and/or that there is dynamic dispatching of static methods happening.
For what it is worth the rules for name resolution are fully specified in the JLS. (See this answer for the JLS text and reference.) The implications are a bit complicated for edge cases like the one you are talking about, but the name resolution rules are not Java version specific, AFAIK.
Java is not designed to "play nice" when people willfully ignore the style rules.
The Java Language Specification deals with that. here the first paragraph of JLS 6.4.2 Obscuring:
A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package. In these situations, the rules of ยง6.5.2 specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. Thus, it is may sometimes be impossible to refer to a type or package via its simple name, even though its declaration is in scope and not shadowed. We say that such a declaration is obscured.
As you already mentioned, FQN must be used instead of the simple name.
A ClassName.class returns the Class object for that particular class. That said and understood, I can't really grasp what the keyword does when used directly in a method.., then, if we write class and follow it immediately with a dot, the list that appears seems to include all that's in scope there, i.e. local variables of the method, other methods and variables(depending on whether the method is static or not), method itself, and class itself..
Coming from its first stated function above, I find myself at odds with this one: I can't tell what it's exactly doing.. way I see it, it's the same word, expect same function at heart, but that doesn't seem to be the case here
Blurry.. I know, but any insight into it is appreciated. Thx.
I get similar behaviour from Netbeans:
However, these are somewhat bogus suggestions.
class.emptyList(), despite being a suggestion, will not compile. This is probably a peculiarity of the way suggestions are computed. If there's a way to get legal code out of these suggestions, I can't think of it.
Note that you get the same suggestions if you just hit CTRL+enter (or whatever keys you have bound to suggestions) on an empty statement.
Usually there are only two circumstances to use the word class:
When defining a class, for example public class MyClass { ... }
With a dot, after a class name, to get the Class object for a type - Class<Person> clazz = Nurse.class
Sometimes you feel you'd like to have a variable called class, but it's a reserved word, so you can't. It's quite common to see variables called clazz for that reason.
Considering everything is object oriented etc, so names have to describe the object and what it is, I have an abstract class that sub classes inherit from. These are all objects on the screen (it's a game), i.e, player, and a weight (trapezoid weight). I have it currently named Character but it doesn't seem fitting as the weight is not a Character itself, it only inherits properties from Character.
Could I call this class "Object" without it breaking conventions? - could someone come up with a more appropriate name?
Technically, you could - but it's a very, very bad idea, so don't.
Longer explanation: The Object class already in Java is java.lang.Object - so there's no technical reason why you could create another Object class in another package, just as you could create another String class in another package. (Actually, technically speaking you could even create your own java.lang.Object, but I'm not even going to go there!)
However:
Could I call this class "Object" without it breaking conventions?
Without breaking convention? Not in the slightest. You should never duplicate such commonly used class names elsewhere, especially those in java.lang. It would be considered incredibly bad code design.
In terms of a better name, Actor or Sprite may be two good alternatives.
Java's Object class is part of the java.lang package which is automatically imported for every class file. If you name your class Object and forget to explicitly import it in other classes, you will have issues, thinking you're using com.custom.Object (your class), but actually using java.lang.Object, the JDK's.
Use a more descriptive name, ApplicationObject.
Yes you can. The class beside the name has the path that is package.
package org.stackoverflow
public class Object {
}
By default java.lang is prohibited package name so you can not do declare
package java.lang
public class Object {
}
The class names does not have to be unique in scope of whole world. Using the class path you are able to override the JVM definition of class.
I'm writing some kind of library. I have an abstract class there. Client-code needs to extend it to use some methods. May happens that user quits application and after he restarts it I need to restore reference to his concrette class. My idea was to save canonical name of user's class and then just make newInstance() for it. However for some reason it can't create the instance. I've made a test:
void foo(AbstractClass a) {
String classname = a.getClass().getCanonicalName();
System.out.println(classname); //Output: "com.test.clientcode.Main.ConcretteClass"
a = null; // here I lost my reference to ConcretteClass for example, so all I have is a classname
Class.forName(classname).newInstance(); //Throws exception: "java.lang.ClassNotFoundException: `com.test.clientcode.Main.ConcretteClass"
}
It's a method within library code. For argument a I give it an instance of concrette user class.
UPDATE: to make things easier: in my library I have a method like above, argument a is a reference to client's ConcretteClass as we see in the output of 2nd line. Then I lose my reference. How can I make a new instance of ConcretteClass if the only thing I know is ConcretteClass' canonical name?
Your approach won't work.
If you want to "restore" the instance you should do in other way instead of simply newInstance. this is one thing. I don't know your concrete requirement, so I cannot answer further on the "restore" part.
I said your approach won't work, because you said your are writing a "library", so I guess client code will import your class, that is, your abstract class is in client codes's classpath. however, the client class won't be in your classpath. that's why you got the classnotfound Ex.
same as if I extend a class from guava for example, how come in guava codes, it knows my class and create an instance of my class?
As we know, in Java, method name is not sufficient to distinguish different methods.
I think (may be wrong), to distinguish a method, it needs the following info:
(className, methodName, methodParameters)
Further,
how to identify a method more efficiently internally?
I heard of "method id". Does it mean there is a mapping between the above triple and an integer, so JVM use only method id after parsing?
If so, is it resided in symbol table?
Thanks!
It's a CONSTANT_NameAndType_info Structure pointing at a method descriptor.
It pretty much consists of the method name, the parameter types, and (somewhat surprisingly) the return type.
I do not understand very well what you are trying to do but I think there are some possible answers nonetheless:
You may be interested in the JNI Method Descriptors, one of the various string formats used internally by the JVM (and by JNI libraries) for identifying Java elements.
It is difficult to know about what you are talking about. The "method id" can be a reference for a java.lang.reflect.Method object, or can be the method descriptor mentioned below, or any other thing. Where did you read about it?
I doubt there is such table inside the JVM. I mean, I doubt there is a global table, because almost always you retrieve a method from a class, even when dealing with it inside the JVM, so it is reasonable to believe the method is stored in the class. It is likewhen we use reflection to retrieve a method:
Class clazz = String.class;
Method method = clazz.getDeclaredMethod("charAt", Integer.TYPE);
System.out.println(method.getName());
Note that I ask the class String for the method, instead of asking some util class to give me the method charAt, which receives an int and is from the class String.
In other words, your identification tuple is almost correct - it just does not have a class:
(methodName, methodParameters)
and, instead of retrieving the method from the JVM passing the class and then the method name and then the parameter types, you retrieve the method directly from the class, giving the class the method name and the parameter types. A subtle difference, for sure, but I think it is what you are wondering about.
This is evident even in the JNI descriptors I mentioned below. For example, the method
long f(int i, Class c);
is represented by the following descriptor:
"(ILjava/lang/Class;)J"
Note that there is no reference to the class of the method.
The excellent documentation on the class file format (already pointed by #Lawence) may give you some insights. I recommend you to read it fully.
1) How to identify a method more efficiently internally?
Internally to what? There are many places where a method might need to be "identified" "internally". In the bytecode compiler, the JIT compiler, the classloader / linker, the classfile representation, reflection API, a debugger and so on. They each have different efficiency concerns.
2) I heard of "method id". Does it mean there is a mapping between the above triple and an integer, so JVM use only method id after parsing?
A method id is used in the classfile representation, and could be used by anything based on that, including the class loader / linker, the JIT compiler and the debugger.
The JVM doesn't parse Java code.
3) If so, is it resided in symbol table?
It might do. It depends on what you mean by "the symbol table". Bear in mind that there are lots of places where method identification is required, throughout the lifecycle of a class. For instance, the Java reflection APIs require method information to implement methods such as getDeclaredMethod(...) and various methods of Method.
Java always differentiate its language elements by their fully qualified names.
Suppose you have a method myMethod(int a, int b) in class MyClass which lies in the package com.mypackage then java will identify the method with the name com.mypackage.MyClass.myMethod(int a , int b).
Just to give you some more insight, it also takes the Class Loader into consideration when there is a need to resolve two identical elements.
It does consider, which class loader was used to load the particular class containing the method to which you are referring. There are four types of class loaders in java. You can read the documention for java.lang.Thread class for this.