Why are there no subclasses of java.lang.Class? - java

java.lang.Class defines multiple methods which only apply to a certain type of class, e.g.:
getComponentType: Only relevant for arrays
getEnumConstants: Only relevant for enums
So why is there, for example, no ArrayClass which defines the getComponentType method instead?

This appears to be more or less a design choice. Since i did not design this language, i cannot answer it with certainty, but i'll try to explain potential reasons for this.
So why is there for example no ArrayClass which defines the getComponentType method instead?
The trick to understanding this is, that the java.lang.Class class is not a direct equivalent to the class you are coding. This specific class is only used to represent the created class at runtime (for example: for the use of reflections).
As from the Java-Doc of the Class (here from Java 7):
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
You are writing custom classes, if you write your code, which means that your created code is the class. If you create a class called the ArrayClass, this is your class. The java.lang.Class class is then only usable at runtime to analyze the class of this specific Object.
For the design in Java, two more layers of complication are added.
First: You can analyze every object, which is a subtype of java.lang.Object. The method getClass is defined here. This means that you are able to introspect any object for any specific detail. If the specific type of the Object is not an enum for example, the class returns null upon calling getEnumConstants. If you had specific sub-types of the java.lang.Class, you would have to cast the instance before introspecting it, which would make it more annoying to work with.
Second: The java.lang.Class object, representing your type is created lazy, within the ClassLoader. Upon referenzing a specific type, the ClassLoader checks whether or not the Class is already loaded and if not, loads it. It then creates the java.lang.Class-Objects, which represents this specific Type. This class-object can then be used, to create instances of your type.
If the java language had different subtypes for the java.lang.Class, the ClassLoader would have to instantiate the correct subtype of the Class, corresponding to what would be needed. If you where able to create custom subtypes of the java.lang.Class, this would get out of hand quickly. How is the ClassLoader supposed to know which Class-instance is connected to your Type? Would you have to write specific Class-instances and somehow mark your created type to use that Class-instance? You could imagine something like this:
public class MyType extends ... implements ... type MyClassInstance
But then, how do you fill up custom fields within your custom java.lang.Class instance? Those complications may be the reason, that the java.lang.Class has a generic type, representing the connected Type. Event though there are a million possible solutions to those complications, there still might be an argument to be made for usability and robustness.
As Oracle point out in there Design Goals of the Java Programming Language:
The system that emerged to meet these needs is simple, so it can be easily programmed by most developers; familiar, so that current developers can easily learn the Java programming language; ...
As much as one would love to see something like this within the language, this feature would make it way more complicated, since it would allow developers to change the behavior of the newInstance method for example. You could introduce an Exception within this Method and one might think, the constructor threw an Exception, even though it did not. This goes into the same (or a similar) direction as Why doesn't Java offer operator overloading?, with that, you are essentially overriding the new keyword.
The Class currently is final (likely because it is a core language construct). This prohibits subtypes of java.lang.Class. If the class should receive subtypes, it has to loose final which means anyone could override any specific detail for a class. Calling getClass could result in any unknown type, that could do anything.
With that, we now only have specific subtypes of classes, we still cannot access them. To do this, we have to do one of the following:
Either add a generic type to the Object like this (i don't want to start a debate about super or extends, this is just an example):
public class Object<T extends Class> {
public final native T getClass();
}
This is required because we want to have certain classes connected to certain objects. With this however, we are not specifying how to instantiate the class. Normally a class is instantiated through the ClassLoader. Again from the JavaDoc:
Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.
This would no longer be viable, except we require certain aspects like a private constructor. Also, we had to provide every custom Class as native C++ code.
The other possibility would be, to define the getClass method in implementations something like this (this code has different generic based issues, but again, just an example):
public class Object {
public <T extends Class<?>> T getClass() {...}
}
public class MyType {
public MyClass getClass() { return new MyClass(); }
}
Which would open the door to more complicated issues introduced earlier. You could now do work in here, that you are not supposed to do. Imagine a InvocationHandler for example. The other issue with this is that now the developer has the freedom to decide whether or not a Class is instantiated only once or multiple times, which would break for example the Class-Based-Programming and of course some aspects of the Java-Language.
Even though i cannot answer with certainty, i hope this helped a bit.

Related

Will the use of Class as key for a HashMap cause undesireable effects?

Consider the following:
Map<Class<?>, Object> myMap = new HashMap<Class<?>, Object>();
Foo fooObject = New Foo();
myMap.put(fooObject.getClass(), fooObject)
Notice that java.lang.Class does not implement the hashCode() method itself, but inherits it from java.lang.Object implicitly. I verified this in JDK 1.8.
Is java.lang.Class safe to use as a key for a java.util.HashMap?
Will myMap.get(Foo.class) always return the values which I put like myMap.put(fooObject.getClass(), fooObject)? Consider the software to have various classloaders and serialization mechanisms. Will it still be the same result? If not... What would be an alternative?
Off the top of my head, would there be any reason to just not use the string class names? E.g. instead use:
myMap.put("Foo", fooObject);
If you are paranoid that maybe there could be more than one Foo class in scope, you could use the full canonical name:
myMap.put(Foo.class.getCanonicalName(), fooObject);
Is java.lang.Class safe to use as a key for a java.util.HashMap?
Yes.
Will myMap.get(Foo.class) always return the values which I put like myMap.put(fooObject.getClass(), fooObject)?
Yes.
Using a Class object as a key in a HashMap is safe. The Class class inherits the Object::equals and Object::hashCode methods. Thus equals for Class objects is testing object identity.
This is the correct semantics for type equality in Java. The implementation of the ClassLoader::defineClass method ensures that you can never get two different Class objects representing the same Java type.
However, there is a wrinkle. The Java Language specification (JLS 4.3.4) states this:
At run time, several reference types with the same binary name may be loaded simultaneously by different class loaders. These types may or may not represent the same type declaration. Even if two such types do represent the same type declaration, they are considered distinct.
(The binary name is related to the FQDN of a named type, and takes account of anonymous classes, and array types.)
What this means is that if you (successfully) call ClassLoader::defineClass for classes with the same fully qualified name in two different classloaders, you will get different Java types. Irrespective of the bytecodes you used. Furthermore, if you attempt to cast from one type to the other one, you will get a class cast exception.
Now the question is does this matter in your use-case?
Answer: probably not.
Unless you (or your framework) are doing tricky things with classloaders, the situation does not arise.
If it does, then you probably need the two types (with the same FQDN and different classloaders) to have the different entries in the HashMap. (Because the types are different!)
But if you need the two types to have the same entry, then you can use the FQDN for the class as the key, which you can obtain using Class::getCanonicalName. If you need to cope with array classes, etc, then use Class::getName which returns the binary name for the type.
What about serialization mechanisms?
A Class object cannot be serialized using Object serialization, since Class does not implement Serializable. If you implement / use some other serialization mechanism that does support the serialization of Class objects, then that mechanism needs to be compatible with JLS 4.3.4.
Instances of Class are unique per ClassLoader so it is not needed to override hashCode or equals.
There is a difference between run-time and compile-time type. It is possible to simultaneously load multiple classes of the same fully-qualified class name, if (and only if) they are loaded by different class loaders. Then such classes are distinct run-time types, and cannot be cast to one another, even if they are identical.
Hence the answer to your question depends simply on which effect you consider desirable:
If you desire to treat those separately loaded and incompatible classes as distinct in your map, use Class as the key. There will never be more than one live instance of Class with the same name and loader, so the Class class correctly does not override the hashCode and equals methods. So it is fine to use it as a HashMap key, although IdentityHashMap will give the same behavior, probably more efficiently.
If you desire to distinguish classes based only on their name, regardless of how (or whether) they were loaded, then use their string name as the map key.
#talex I tested it like below and you seem to be right:
public class ClassUnique {
public static void main(String [] args) throws ClassNotFoundException {
Class<?> c1 = Class.forName("java.util.Date");
Class<?> c2 = Class.forName("java.util.Date");
System.out.println(c1.equals(c2));
}
}
Output is true
EDIT: #Maarten I think you are right. Especially if you are running within an application container like Websphere or Weblogic there might be multiple class loaders in play which could screw this up. So in the end the simplest correct solution would be to just use the Class instance itself.
I would consider using IdentityHashMap. It does not rely on equals.
This class is designed for use only in the rare cases wherein reference-equality semantics are required.

Java inheritance, two-step inheritance

I have the main abstract class that is a base for bunch of classes. Some of them does not need all the fields and methods from the main abstract class, so I have created second abstract class and splitted main abstract class into two parts. The main abstract class contains, for example, a, x fields and their getters/setters, the second abstract class inherits from the main and contains additional b, c fields and their getter/setters. There are simple classes that are inheriting from the main class,and more complicated are inheriting from the second class. I want to create objects of each class as instances of the main class. Is it right way to do that? I have to type check and cast when I want to use methods from the second abstract class. It makes my code complicated. How can I solve this problem?
MainAbstractClass ---> SecondAbstractClass ---> MyComplicatedClasses
|
|
V
MySimpleClasses
One of the OO principles is Favor composition over inheritance.
This means that common behavior is not provided through base classes but via Component classes which are passed in via dependency injection (preferably as constructor parameters.
The answer depends on your actual needs.
You can instead choose to store the extended abstract class specific fields in a class that does not implement your base class and make it a member of more complicated classes.
You can choose to keep everything in a single base class and nothing forces you to use all the fields of an interface in every class that implemented your interface.
You can also keep using your approach but since you store the classes as an instance of the base class, it will be hard to read.
I believe that if you think code does not look very good, it is probably not good. However, there is usually no single answer to this kind of design questions and the best solution is relative to your preferences.
I think this need of type cast is a smell of fragile design. Here when we assume MyComplicatedClass ISA KIND OF MainAbstractClass as shown by TJ Crowder then object must behave as MainAbstractClass (meaning it can honor only API of MainAbstractClass). If it expects special treatment as MyComplicatedClass its false commitment and will need Casting. Such casting (by identifying type) goes against OO principles and kills polymorphism. Later this will end up in Ladder of InstanceOf and type casts as in the scenarios rightly pointed out by T.J. Crowder.
I would suggest readdress the design. e.g. though our all user defined type instances ARE KIND OF Object, but we use Object API only for methods defined in Object class. We do not use Object o = new MyClass(). There are occasions in frameworks or like Object.equals() method where type cast is needed as API is defined before even concrete extension is written. But it is not a good idea for such simple complete (without open hooks for extensions) Hierarchies.

Get method from Class then invoke via Object

In order to invoke a method on a object via reflection, the only way I know how to do it is like so:
Object o = ...;
Method m = o.getClass().getMethod("methodName",null);
Object x = m.invoke(o,null);
Why doesn't Java have a getMethods method in the Object class? (As well as getSuperClass, getFields, etc, etc).
So we could just do something like:
Object x = o.invoke("methodName",null);
Why not? I assume this is for performance reasons.
(Also as a side note. In English, it makes more sense to say 'subject invokes object', so that would be in programming terms, object invoke method. But with Java we get 'method invoke on object'. Glad I could confuse you today.)
I believe the reason is that java.lang.Object is supposed to serve as the root of the class hierarchy and any method on it should pertain to instances of that object rather than the concept of an object.
Adding reflection utility methods to Object would spoil this. You'd have a choice of calling o.myMethod() or o.invoke("myMethod", null) and this would introduce a style of programming in Java that is not compile-safe, in that there is no compile-time guarantee that "myMethod" exists in the latter. This would make it very easy for developers to do away with type safety and just use .invoke all the time without bothering to consider proper object-oriented design.
By forcing developers to explicitly ask for an instance of Class, we maintain this separation between the reflection API and "concrete" Java. So, while it can sometimes be a pain, it's good to encourage developers to code properly. Also, it means that the OOP concept of an object is represented by java.lang.Object and the concept of a class is represented by java.lang.Class, which is a nice, clear distinction of responsibility.
The class Object
is the root of the class hierarchy.
It describes behavior that every class will need.
Any additional behavior is described by the sub classes, but a sub class doesn't necessarily have to have behavior. You can declare a class of constants, an enum, or even an array. Then it wouldn't make sense to have an invoke method on those.

Java Object superclass

I have a weird Java question:
As we know:
All Java classes extend java.lang.Object
All Java classes cannot extend itself
Then, java.lang.Object must extend java.lang.Object, which is itself, therefore, it should be impossible. How is Object implemented in Java?
Object is an exception to the first rule, and has no superclass. From JLS3 8.1.4:
The extends clause must not appear in the definition of the class Object, because it is the primordial class and has no direct superclass.
You can also try it out with reflection:
Object.class.getSuperclass(); // returns null
You'd be better off thinking of this as:
All java classes must implement the interface implied by the methods in java.lang.Object.
The concrete class java.lang.Object provides default implementations of these functions.
All other java classes are derived from the object java.lang.Object and may choose to use or override the default implementations of the methods.
The two main points are: all the classes must implement the implied interface and the Java language spec gives you (forces upon you?) default implementations for these methods for free.
Object does not extend itself. It is the superclass for all other objects in the Java language. Think of it as being the level-0 (or root) class of all the objects in the Java API tree - including any objects you create as well.
I also just want to point out that your question is proven impossible by rule #2 that you posted. Your logic used to justify your question only takes #1 into account and is therefore extremely flawed.

Java abstract static Workaround

I understand that neither a abstract class nor an interface can contain a method that is both abstract and static because of ambiguity problems, but is there a workaround?
I want to have either an abstract class or an interface that mandates the inclusion of a static method in all of the classes that extend/implement this class/interface. Is there a way to do this in Java? If not, this may be my final straw with Java...
EDIT 1: The context of this problem is that I have a bunch of classes, call them Stick, Ball, and Toy for now, that have a bunch of entries in a database. I want to create a superclass/interface called Fetchable that requires a static method getFetchables() in each of the classes below it. The reason the methods in Stick, Ball, and Toy have to be static is because they will be talking to a database to retrieve all of the entries in the database for each class.
EDIT 2: To those who say you cannot do this in any language, that is not true. You can certainly do this in Ruby where class methods are inherited. This is not a case of someone not getting OO, this is a case of missing functionality in the Java language. You can try to argue that you should never need to inherit static (class) methods, but that is utterly wrong and I will ignore any answers that make such points.
You have a couple of options:
Use reflection to see if the method exists and then call it.
Create an annotation for the static method named something like #GetAllWidgetsMethod.
As others have said, try to not use a static method.
There are lots of answers about 'this does'nt make sense..' but indeed I met a similar problem just yesterday.
I wanted to use inheritance with my unit tests. I have an API and several its implementations. So I need only 1 set of unit tests for all implementations but with different setUp methods which are static.
Workaround: all tests are abstract classes, with some static fields with protected access modifier. In all implementations I added static methods which set these static fields. It works rather nice, and I avoided copy and paste.
I too am dealing with this problem. For those that insist that it "doesn't make sense", I would invite you to think outside of that semantic box for a moment. The program I am working with is inherently about reflection.
Reflection, as you know, can take three orders of magnitude longer than straight-up binary function calling. That is an inevitable problem, and the software needs to port to as many machines as possible, some of which will be 32 bit and slower than my development machine to begin with. Thus, the applicability of a class to the requested operation needs to be checked via a static method, and all of the reflective methods are run at once during module booting.
Everything works, first and foremost. I've built the entire thing. The only catch is that a module can be compiled in a .class without compile time checking to see if the identifying static function exists at all, resulting in an innately useless class. Without the identifier, and its included information, for security's sake the module is not loaded.
I clearly understand the issue with the complete definition of "abstract" and "static", and understand that they don't make sense together. However, the ability to have a class method that is compiler-enforced for inclusion is lacking in Java, and as much as I like the language, I miss it. Thus, this is a human constraint on every programmer that ever works on the software, which I'm sure we can all agree is a pain.
There's a lot of 'this makes no sense' or 'this can't be because' and 'why do you want it?' (or worse: 'you don't have to want it!') in all those answers. However, these answers also indirectly give reasons why it should be possible.
It must be differentiated between the concept and the implementation.
Sure, overriding a static method makes no sense. And it also isn't what the question was about.
It was asked for a way to force implementation of a certain static method (or constant or whatever) in every derived class of an abstract class. Why this is required it the matter of the one who wants to write an appllication with Jave, and no business of anyone else.
This has nothing to do with how the compiler compiles the method and how it is done at runtime.
Why shoudl it be possible? because there are things that are class specific (and not instance specific) and therefore should be static, while they NEED to be impleented in every single subclass (or class that implements an interface).
Let's say there is an abstract class 'Being'. Now there are subclasses like 'animals' and 'plants'.
Now there are only mammals and fishes allowed for animals. This information is specific to the animals class, not to any instance nor doe sit belong to any superclass or subclass. However, this information must be provided by teh class, not an instance, because it is required to properly construct an animal instance. So it MUST be there and it CANNOT be in the instance.
In fact, Java has such a thing- Every object has a class specific field 'class'. It is class-specific, not inherited, no override and it must be there. Well the compiler creates it implicitly, but obviously the compiler CAN do it. So why not allowing this for own fields too.
After all, it is just a matter of definition how the combination 'abstract static' is interpreted when the compiler checks the intheritance chain for abstract functions.
Nobody was ever demanding that there should be an inheritance of the superclass class functions (which could still make some sense, depending on what this function actually does - after all classes inherit static functions of their superclasses, even though you might get a warning that you should access it directly when you call it by the subclass))
But to summarize: the Java language offers no way to do it at compile time while there is no reason (othe rthan plain dogmatic) to not doing so.
The only way is to write a static final function to the abstract class that tries to find the static function/field of the subclass when it is loaded (or loads all existing subclasses and checks them). If properly made, it gives a runtime error on first use. Complex and dirty but better than nothing. At least it prevents bugs where you get the information from the wrong superclass.
It won't work for interfaces, though.
A type system allows you to express some constraints among types, but it's limited. That's why javadocs are littered with constraints in human language, asking people to follow rules that the compiler cannot check.
if you want to extend it beyond what language provides natively, you can write your own static analysis tool. that is not uncommon. for example: findbug. also IDEs do that too, they checking thing beyond what language dictates. you can write a plug in to enforce that a subclass must have a static method of such signature.
in your case, it's not worth it. have javadoc in the superclass urge implementors to include a static method, that's good enough.
I'll provide a convoluted way of expressing your constraint anyway, but DO NO DO IT. people get really carried away of make everything checkable at compile time, at the price of making code unreadable.
interface WidgetEnumerator
{
List getAllWidgets();
}
public class Abs<T extends WidgetEnumerator>
{
static List getAllWidgets(Class<? extends Abs> clazz){ ... }
}
public class Sub extends Abs<SubWidgetEnumerator>
{
}
public class SubWidgetEnumerator implements WidgetEnumerator
{
public List getAllWidgets() { ... }
}
How it works: for any subclass of Abs, it is forced to provide an implementation of WidgetEnumerator. subclass author cannot forget that. Now invocation Abs.getAllWidgets(Sub.class) contains sufficient information to resolve that implementation, i.e. SubWidgetEnumerator. It is done through reflection, but it is type safe, there are no string literals involved.
I think I can give you a better answer after seeing your edits--your best bet is probably a factory pattern. (Not lovely, but better than singleton).
abstract class Widget
public static Widget[] getAllWidgetsOfType(Class widgetType) {
if(widgetType instanceof ...)
}
class Ball extends Widget
class Stick extends Widget
class Toy extends Widget
This is not a very good way to do it, but it's typical. Hibernate is the tool you would normally use to solve this problem, this is exactly what it's designed for.
The big problem is that it requires editing the base class whenever you add a new class of a given type. This can't be gotten around without reflection. If you want to use reflection, then you can implement it this way (Psuedocode, I'm not going to look up the exact syntax for the reflection, but it's not much more complex than this):
public static Widget[] getAllWidgetsOfType(Class widgetType) {
Method staticMethod=widgetType.getStaticMethod("getAllInstances");
return staticMethod.invoke();
}
This would give the solution you were asking for (to be bothered by the need to modify the base class each time you add a child class is a good instinct).
You could also make it an instance method instead of a static. It's not necessary, but you could then prototype the method (abstract) in Widget.
Again, all this is unnecessary and sloppy compared to Hibernate...
Edit: If you passed in a live "Empty" instance of a ball, stick or toy instead of it's "Class" object, you could then just call an inherited method and not use reflection at all. This would also work but you have to expand the definition of a Widget to include an "Empty" instance used as a key.
Static methods are relevant to an entire class of object, not the individual instances. Allowing a static method to be overridden breaks this dictum.
The first thing I would consider is to access your database from a non-static context. This is actually the norm for Java apps.
If you absolutely must use a static method, then have it parameterised with instance specific arguments (of a generic type) to allow the different subclasses to interact with it. Then call that single static method from you polymorphic methods.
No. You can't do that. If you're willing to compromise and make the method non-static or provide an implementation of the static method in your abstract class, you'll be able to code this in Java.
Is there a way to do this in Java?
I don't think there is a way to do this in any language. There's no point to it, since static methods belong to a class and can't be called polymorphically. And enabling polymorphic calls is the only reason for interfaces and abstract classes to exist.
Create a context interface containing your method with a name that matches your problem domain. (Name it "World" if you absolutely have to, but most of the time there's a better name)
Pass around implementation instances of the context object.
Ok, maybe my question was poorly asked, it seems like most of you didn't get what I was trying to do. Nonetheless, I have a solution that is somewhat satisfactory.
In the abstract super class, I am going to have a static method getAllWidgets(Class type). In it I'll check the class you passed it and do the correct fetching based on that. Generally I like to avoid passing around classes and using switches on stuff like this, but I'll make an exception here.
static methods can't be abstract because they aren't virtual. Therefore anywhere that calls them has to have the concrete type with the implementation. If you want to enforce that all implementations of an interface have a certain static method, then that suggests a unit test is required.
abstract class A
{
public static void foo()
{
java.lang.System.out.println("A::foo");
}
public void bar()
{
java.lang.System.out.println("A::bar");
}
}
class B extends A
{
public static void foo()
{
java.lang.System.out.println("B::foo");
}
public void bar()
{
java.lang.System.out.println("B::bar");
}
}
public class Main
{
public static void main(String[] args)
{
B b = new B();
b.foo();
b.bar();
A a = b;
a.foo();
a.bar();
}
}
For what it is worth I know exactly what you are trying to do.
I found this article while searching for the reasons I can't do it either.
In my case I have HUNDREDS of classes that inherit from a central base base and I want simply to get a reference like this:
ValueImSearchingFor visf = StaticClass.someArbitraryValue()
I do NOT want to write/maintain someArbitraryValue() for each and every one of hundreds of the inherited classes -- I just want to write logic once and have it calc a Unique Class-Sepcific value for each and every future written class WITHOUT touching the base class.
Yes I completely get OO - I've been writing Java for about as long as it's been available.
These specific classes are more like "Definitions" as opposed to actual Objects and I don't want to instantiate one every time I just need to see what someArbitraryValue() actually is.
Think of it as a PUBLIC STATIC FINAL that allows you to run a Method ONCE to set it initially. (Kinda like you can do when you define an Enum actually...)
I'd make a WidgetCollection class with an abstract Widget inner class.
You can extend the WidgetCollection.Widget class for each of your types of Widget.
No static methods necessary.
Example (not compiled or tested):
class WidgetCollection<W extends Widget> {
Set<W> widgets = new HashSet<W>();
Set<W> getAll() {
return widgets;
}
abstract class Widget {
Widget() {
widgets.add(this);
}
abstract String getName();
}
public static void main(String[] args) {
WidgetCollection<AWidget> aWidgets = new WidgetCollection<AWidget>();
a.new AWidget();
Set<AWidget> widgets = aWidgets.getAll();
}
}
class AWidget extends Widget {
String getName() {
return "AWidget";
}
}
It doesn't make sense to do what you're asking:
Why can't static methods be abstract in Java

Categories

Resources