Why is `Class` class final? - java

Answering a question here at SO, I came up to a solution which would be nice if it would be possible extend the Class class:
This solution consisted on trying to decorate the Class class in order to allow only certain values to be contained, in this case, classes extending a concrete class C.
public class CextenderClass extends Class
{
public CextenderClass (Class c) throws Exception
{
if(!C.class.isAssignableFrom(c)) //Check whether is `C` sub-class
throw new Exception("The given class is not extending C");
value = c;
}
private Class value;
... Here, methods delegation ...
}
I know this code does not work as Class is final and I wonder why Class is final. I understand it must have to do with security but I can't imagine a situation where extending Class is dangerous. Can you give some examples?
By the way, the closer solution for the desired behavior I can reach is:
public class CextenderClass
{
public CextenderClass(Class c) throws Exception
{
if(!C.class.isAssignableFrom(c)) //Check whether is `C` sub-class
throw new Exception("The given class is not extending C");
value = c;
}
public Class getValue() {
return value;
}
private Class value;
}
But it lacks the beauty of transparent decoration.

According to comments in the Class class Only the Java Virtual Machine creates Class
objects..
If you were allowed to extend classes, then a problem would arise, should you be allowed to create custom Class objects?. If yes, then it would break the above rule that only the JVM should create Class Objects. So, you are not given that flexibility.
PS : getClass() just returns the already created class object. It doesn't return a new class object.

That's a very good question but is only an instance of a more general problem and although #TheLostMind 4 years ago has just responded (considered an implementation point of view) in terms of JVM rules/restrictions the problem still remain: why JVM pose that rules? There have to be a plausible reason. We have to examine it from a more abstract level(point of view)
Short answer:
Plausibly all that has to do with type safety and as all we know Java is a strongly typed language and permits no one to change that fact.
Elaborate Answer(with some context so to be understandable for everyone):
All the story start from static and dynamic binding.
The flexibility given by subtype polymorphism makes the declared (static) type of an object in general different from its run-time (dynamic) type.
The run-time type is in general a subtype of the static type.
e,g.
AClass a = new AClass();
AsubClass b = new AsubClass(); // AsubClass is derived from AClass
a=b;
The static type of a is AClass and after the assignment a=b; its runtime type is AsubClass. This has implications on selection of the most appropriate method when executing a message.
Now consider the class Vehicle given
below.
public class Vehicle {
private int VIN; // Vehicle Identification Number
private String make;
public boolean equals(Object x) {
return (VIN == (Vehicle)x.VIN);
}
// other methods
}
The method equals in the root class java.lang.Object is defined as the test on object identity.
This is the only meaningful way of defining the equality of objects in general.
That is, two objects are equal if they have the same identity.
In a specific class a more suitable meaning of equality may be more appropriate. In the above class two vehicles are considered equal if their VINs (vehicle identification numbers) are equal.
So the method equals is redefined accordingly in the
class Vehicle. This redefinition of an inherited
method is called overriding.
Note that the signatures of the inherited method arguments are required to remain the same in the subclass according to the function subtyping rule.
This creates an awkward situation because in the class Vehicle we would like to refer to the VIN field of the argument, and Object does not have such a field. This is why the type cast (Vehicle)x specifies that the intent is to view x as a Vehicle. There is no way to
verify this cast statically, hence a dynamic check is generated by the compiler. This is an instance of dynamic type checking.
In order for overriding to work correctly the method to be invoked is determined by the dynamic type of the receiver object (also known as dynamic dispatch (selection) of methods and is the most important case of dynamic binding in OO languages.)
e.g.
Object a = new Object();
Object b = new Object();
Vehicle aV = new Vehicle();
Vehicle bV = new Vehicle();
a=aV;
b=bV;
. . .
a.equals(b)
. . .
The method to be invoked in response to the message a.equals(b) will be the method equals overridden in the class Vehicle because the run time type of a is Vehicle.
There are situations in which overriding a method might be problematic and should not be allowed. A good example is the Java.lang.Object 's getClass() . This method has a particular implementation in the underlying virtual platform, which guarantees that invocation of this method will indeed return the class object of the receiver of the method.
Allowing overriding would have serious implications on the intended semantics of this method creating nontrivial problems in dynamic type checking. This is probably why the getClass() is declared as final.
e.g.
public class Object {
public final Class getClass();
....
}
Finally The class Class in Java is final, i.e. cannot be extended, and hence none of its methods can be overridden. Since the class Class has only introspection methods, this guarantees safety of the type system at run-time, i.e., the type information cannot be mutated at run time.
to extend the concept a bit more ...
Dynamic dispatch (selection) of methods based on the type of the receiver object is the basic technique in object-oriented languages.
It brings the type of flexibility that makes the whole object-oriented paradigm work.
Adding new types by inheritance to an already compiled and running application requires only compilation and linking of the newly introduced types without recompiling the existing application. However, this flexibility comes with some penalty in efficiency because the decision about method selection is postponed to runtime. Modern
languages have efficient techniques for dynamic dispatch of methods, but some languages like C++ and C# try to avoid the associated cost by providing a static binding (method selection) option. In C#, methods are statically bound unless they are explicitly declared as virtual.
e.g.
public class Object {
public virtual boolean equals(Object x);
// other methods
}
Overriding this method in C# will be indicated by an explicit keyword override.
e.g.
public class Vehicle {
private int VIN;
private String make;
public override boolean equals(Object x) {
return (VIN == (Vehicle)x.VIN);
}
// other methods
}
Methods whose receiver is the class object are always bound statically.
The reason is that there is only one class object for all objects of that class. Since the receiver is known at compile time, there is no need to postpone method selection to run time. These methods are thus declared as static to indicate that they belong to the class itself.
An example is the method numberOfVehicles of the class Vehicle The number of vehicles is not the property of individual vehicle objects. It is the
property of all objects of the class Vehicle, hence it belongs to the class itself.
e.g.
public class Vehicle {
// fields;
public static int numberOfVehicles();
// other methods
}
We can summarize all the above discussion as follows:
– The basic mechanism for selecting a method for executing a message (method
dispatch) in object-oriented languages is dynamic. It is based on the run-time type of the receiver object.
– The receiver of a static (i.e. class) method is the class object. Since there is only
one class object of a given type, selection of a static method is static.
– Some languages (C++ and C#) allow a choice of static versus dynamic method dispatch. Although this is done for the reasons of efficiency, it has been shown that when both dispatch mechanisms are used in a program, that may obscure the
meaning of the program.

Related

Why does Java bind variables at compile time?

Consider the following example code
class MyClass {
public String var = "base";
public void printVar() {
System.out.println(var);
}
}
class MyDerivedClass extends MyClass {
public String var = "derived";
public void printVar() {
System.out.println(var);
}
}
public class Binding {
public static void main(String[] args) {
MyClass base = new MyClass();
MyClass derived = new MyDerivedClass();
System.out.println(base.var);
System.out.println(derived.var);
base.printVar();
derived.printVar();
}
}
it gives the following output
base
base
base
derived
Method calls are resolved at runtime and the correct overridden method is called, as expected.
The variables access is instead resolved at compile time as I later learned.
I was expecting an output as
base
derived
base
derived
because in the derived class the re-definition of var shadows the one in the base class.
Why does the binding of variables happens at compile time and not at runtime? Is this only for performance reasons?
The reason is explained in the Java Language Specification in an example in Section 15.11, quoted below:
...
The last line shows that, indeed, the field that is accessed does not depend on the run-time class of the referenced object; even if s holds a reference to an object of class T, the expression s.x refers to the x field of class S, because the type of the expression s is S. Objects of class T contain two fields named x, one for class T and one for its superclass S.
This lack of dynamic lookup for field accesses allows programs to be run efficiently with straightforward implementations. The power of late binding and overriding is available, but only when instance methods are used...
So yes performance is a reason. The specification of how the field access expression is evaluated is stated as follows:
If the field is not static:
...
If the field is a non-blank final, then the result is the value of the named member field in type T found in the object referenced by the value of the Primary.
where Primary in your case refers the variable derived which is of type MyClass.
Another reason, as #Clashsoft suggested, is that in subclasses, fields are not overriden, they are hidden. So it makes sense to allow which fields to access based on the declared type or using a cast. This is also true for static methods. This is why the field is determined based on the declared type. Unlike overriding by instance methods where it depends on the actual type. The JLS quote above indeed mentions this reason implicitly:
The power of late binding and overriding is available, but only when instance methods are used.
While you might be right about performance, there is another reason why fields are not dynamically dispatched: You wouldn't be able to access the MyClass.var field at all if you had a MyDerivedClass instance.
Generally, I don't know about any statically typed language that actually has dynamic variable resolution. But if you really need it, you can make getters or accessor methods (which should be done in most cases to avoid public fields, anyway):
class MyClass
{
private String var = "base";
public String getVar() // or simply 'var()'
{
return this.var;
}
}
class MyDerivedClass extends MyClass {
private String var = "derived";
#Override
public String getVar() {
return this.var;
}
}
The polymorphic behaviour of the java language works with methods and not member variables: they designed the language to bind member variables at compile time.
In java, this is by design.
Because, the set up of fields to be dynamically resolved would make things to run a bit slower. And in real, there's not any reason of doing so.
Since, you can make your fields in any class private and access them with methods which are dynamically resolved.
So, fields are made to resolved better at compile time instead :)

Cast base object to derived class

I have two classes:
class Base {
public String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Derived extends Base {
public String getValue() {
return name + " foo";
}
}
And an object created:
Base foo = new Base();
foo.setName("John");
Derived bar = (Derived) foo;
This simple example gives ClassCastException exception:
java.lang.ClassCastException: Base cannot be cast to Derived
Is it possible somehow to extend existing object with extra read-only methods ?
With Base foo = new Base(); you're saying that you have a Cat, but all of the sudden you're trying to convert it to Persian cat, which would have succeeded, if all the cats were Persian ones. This is not true and that's why you get a ClassCastException.
You have to do:
Base foo = new Derived();
Cast base object to derived class
You can't cast objects, you can only cast references. The object is unchanged either way.
If you create a Base (new Base), that's all you have. You can't then call your reference to it a Derived because it isn't a Derived, it's a Base. (Which is why you get the ClassCastException: At runtime, the JVM checks what you're referring to to make sure it really can be referred to that way.)
The other direction works:
Derived d = new Derived();
Base b = d;
...because the object that d refers to is a Derived, and Derived extends Base, meaning that it has an is a relationship with Base: All Derived objects are also Base objects.
The converse is not true: All Base objects are not Derived objects. Attempts to treat them as though they were (by casting references) will fail.
You can define a Derived constructor that accepts a Base and copies its state as part of building a new object. But you can't change the type of the actual object; you have to create a new object with equivalent state.
Just pretend:
Derived bar = (Derived) foo;
worked!!!
class Base doesn't have the getValue() method, so
Base foo = new Base();
foo does't have it.
But as bar is a reference of class Derived so you can call bar.getValue().
So, if you call bar.getValue() what will happen (there is no any getValue() in bar) .?
The basic concept is all child class can be treated as a Parent class. Because child class have almost everything which the parent class have.
But as you can add anything later on child class so Parent class object can't be casted to a child class object.
extend existing object
From the basic of OOP object is an instance (real thing) created form a Class (the blue print). If there is a way then it's gonna violate the basic rule.
The core concept of ObjectOrientation is not derivation (or inheritance) but abstraction. It means: If you want that all of your derived Types (classes) have an operation 'genName()' then it is a very good and core idea to have the class Base with this feature. To invoke this method for all of your objects based on class Base, you can use the
Base ref = (Base)anyDerivedObject;
ref.getName();
Thas is a downcast. The compiler checks whether the downcast is possible. It never throws a ClassCastException if Base is really a Base class.
A second fundamental property of ObjectOrientation are virtual operations (methods). It means the derived class can implement the
#Override public String getValue() {
return name + " foo";
}
Please use the #Override annotation in Java for a obvious and safe programming style. If you invoke
ref = getName();
the derived operation of Derived is invoked if the object which is referred by 'ref' is an instance of 'Derived'. That is done with the virtual table or dispatch table which is also present in Java (usual known from C++).
An upcast is:
Derived ref2 = (Derived)ref;
whereby the type of ref is Base, following the example above. The Java-compiler checks whether or not 'Derived' is derived from the type of 'ref', from 'Base'. If it isn't so the compiler forces an error. But if the references are related, the compiler cannot know whether the referenced object is proper. Therefore
Derived bar = (Derived) foo;
from the introducing example fails. The referenced object is not instanceof Derived. That can be only detect on runtime, not on compiletime.
Consider that all Variables in Java are references, never objects itself (excluding the 7 basic types int, short, char etc.). Objects (instances) in Java are always located in the heap and they are referenced in the operations. That is a fundamental concept of Java for safe programming. In C++ there are programming errors possible, which are difficult to find. The calculation time overhead for this concept is not so far.

Motivation for Using Static Factory Methods

The motivation for using Static Factory methods staes as:
The most obvious motivation for Replace Constructor with Factory
Method comes with replacing a type code with subclassing.
You have an object that often is created with a type code but now
needs subclasses. The exact subclass is based on the type code.
However, constructors can only return an instance of the object that
is asked for. So you need to replace the constructor with a factory
method.
Can anyone please explain this with code? And what does this type code mean?
A second advantage that a factory method has over a bare constructor is that it can return an existing object. The Integer.valueOf(int) method makes good use of this. By contrast, new always creates a new object.
Finally, if we broaden the discussion slightly, a non-static factory method (e.g. in the form of a factory object) allow you use polymorphism to implement different object creation strategies.
And what does this type code mean?
You need to read this in the context of the page that you got this from. What the page is talking about is a single class that represents different "types" of thing. (In the example given, it is different types of employee represented by one Employee class.) The "type code" is simply the attribute of the class that discriminates the different types.
Imagine we have a Person class with a field called type to indicate if that person is a teacher or a student. This will be the type code.
Now imagine we replace this type field with an object hierarchy: Person class with 2 subclasses Teacher and Student.
If I use the constructors then I can only create a specific type of person i.e. new Teacher() or new Student()
but if I want a method that creates a different kind of person based on some logic then I can do:
public static Person newPerson() {
// can return either a Teacher or a Student
}
A constructor can only return one implementation, however a static factory method can return any number of implementations, often a sub-class of the class referred to. Static factory methods also have the advantage of being named so you can have different behaviour for the same arguments.
e.g. These two methods return a sub-class of EnumSet (based on the number of elements in the enum) with different values based on the name (even though the arguements are the same)
EnumSet<MemoryType> memoryTypes = EnumSet.noneOf(MemoryType.class);
EnumSet<MemoryType> memoryTypes2 = EnumSet.allOf(MemoryType.class);
From the source
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
You can see it has one implementation for smaller enum sets and another for larger ones.

Java interfaces and types

Let's say you have some Java code as follows:
public class Base{
public void m(int x){
// code
}
}
and then a subclass Derived, which extends Base as follows:
public class Derived extends Base{
public void m(int x){ //this is overriding
// code
}
public void m(double x){ //this is overloading
// code
}
}
and then you have some declarations as follows:
Base b = new Base();
Base d = new Derived();
Derived e = new Derived();
b.m(5); //works
d.m(6); //works
d.m(7.0); //does not compile
e.m(8.0); //works
For the one that does not compile, I understand that you are passing in a double into Base's version of the m method, but what I do not understand is... what is the point of ever having a declaration like "Base b = new Derived();" ?
It seems like a good way to run into all kinds of casting problems, and if you want to use a Derived object, why not just go for a declaration like for "e"?
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java. The way I learned it earlier this summer was, every object has one class, which corresponds to the name of the class following "new" when you instantiate an object, but an object can have as many types as it wants. For example, "e" has type Base, Derived, (and Object ;) ) but its class is Derived. Is this correct?
Also, if Derived implemented an interface called CanDoMath (while still extending Base), is it correct to say that it has type "CanDoMath" as well as Base, Derived, and Object?
I often write functions in the following form:
public Collection<MyObject> foo() {}
public void bar(Collection<MyObject> stuff){}
I could just as easily have made it ArrayList in both instances, however what happens if I later decide to make the representation a Set? The answer is I have a lot of refactoring to do since I changed my method contract. However, if I leave it as Collection I can seamlessly change from ArrayList to HashSet at will. Using the example of ArrayList it has the following types:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
There are a number of cases where confining yourself to a particular (sub)class is not desired, such as the case you have where e.m(8.0);. Suppose, for example, you have a method called move that moves an object in the coordinate graph of a program. However, at the time you write the method you may have both cartesian and radial graphs, handled by different classes.
If you rely on knowing what the sub-class is, you force yourself into a position wherein higher levels of code must know about lower levels of code, when really they just want to rely on the fact that a particular method with a particular signature exists. There are lots of good examples:
Wanting to apply a query to a database while being agnostic to how the connection is made.
Wanting to authenticate a user, without having to know ahead of time the strategy being used.
Wanting to encrypt information, without needing to rip out a bunch of code when a better encryption technique comes along.
In these situations, you simply want to ensure the object has a particular type, which guarantees that particular method signatures are available. In this way your example is contrived; you're asking why not just use a class that has a method wherein a double is the signature's parameter, instead of a class where that isn't available. (Simply put; you can't use a class that doesn't have the available method.)
There is another reason as well. Consider:
class Base {
public void Blah() {
//code
}
}
class Extended extends Base {
private int SuperSensitiveVariable;
public setSuperSensistiveVariable(int value) {
this.SuperSensistiveVariable = value;
}
public void Blah() {
//code
}
}
//elsewhere
Base b = new Extended();
Extended e = new Extended();
Note that in the b case, I do not have access to the method set() and thus can't muck up the super sensitive variable accidentally. I can only do that in the e case. This helps make sure those things are only done in the right place.
Your definition of type is good, as is your understanding of what types a particular object would have.
What is the point of having Base b = new Derived();?
The point of this is using polymorphism to change your implementation. For example, someone might do:
List<String> strings = new LinkedList<String>();
If they do some profiling and find that the most common operation on this list is inefficient for the type of list, they can swap it out for an ArrayList. In this way you get flexibility.
if you want to use a Derived object
If you need the methods on the derived object, then you would use the derived object. Have a look at the BufferedInputStream class - you use this not because of its internal implementation but because it wraps an InputStream and provides convenience methods.
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java.
It sounds like your teacher is referring to Interfaces and Classes as "types". This is a reasonable abstraction, as a class that implement an interface and extends a class can be referred to in 3 ways, i.e.
public class Foo extends AbstractFoo implements Comparable<Foo>
// Usage
Comparable<Foo> comparable = new Foo();
AbstractFoo abstractFoo = new Foo();
Foo foo = new Foo();
An example of the types being used in different contexts:
new ArrayList<Comparable>().Add(new Foo()); // Foo can be in a collection of Comparable
new ArrayList<AbstractFoo>().Add(new Foo()); // Also in an AbstractFoo collection
This is one of the classic problems on object oriented designs. When something like this happens, it usually means the design can be improved; there is almost always a somewhat elegant solution to these problems....
For example, why dont you pull the m that takes a double up into the base class?
With respect to your second question, an object can have more than one type, because Interfaces are also types, and classes can implement more than one interface.

how to access instance that 'owns' a method in java?

in java, is it possible to access the instance to which a method belongs, given only the method?
for example:
public class ClassA {
private ClassB instanceB = new ClassB();
// ...
private void sendMethod () {
instanceB.receiveMethod(foo);
}
public void foo () {}
}
public class ClassB {
public void receiveMethod (Method method) {
Object o = foo.getInstanceOwner(); // just made that part up...
}
}
my feeling is that methods belong to classes, not instances of a class, so the answer is no, but maybe there's some sneaky reflection technique i don't know about. i could always pass 'this' along with method foo, but that seems like extra baggage.
Taken from
A Method provides information about, and access to, a single method on a class or interface. The reflected method may be a class method or an instance method (including an abstract method).
A Method permits widening conversions to occur when matching the actual parameters to invoke with the underlying method's formal parameters, but it throws an IllegalArgumentException if a narrowing conversion would occur.
You can call Method#invoke but you will need the instance of the object you want to call the method on, from the method doc:
Invokes the underlying method
represented by this Method object, on
the specified object with the
specified parameters. Individual
parameters are automatically unwrapped
to match primitive formal parameters,
and both primitive and reference
parameters are subject to method
invocation conversions as necessary.
If the underlying method is static,
then the specified obj argument is
ignored. It may be null.
If the number of formal parameters
required by the underlying method is
0, the supplied args array may be of
length 0 or null.
If the underlying method is an
instance method, it is invoked using
dynamic method lookup as documented in
The Java Language Specification,
Second Edition, section 15.12.4.4; in
particular, overriding based on the
runtime type of the target object will
occur.
If the underlying method is static,
the class that declared the method is
initialized if it has not already been
initialized.
If the method completes normally, the
value it returns is returned to the
caller of invoke; if the value has a
primitive type, it is first
appropriately wrapped in an object.
However, if the value has the type of
an array of a primitive type, the
elements of the array are not wrapped
in objects; in other words, an array
of primitive type is returned. If the
underlying method return type is void,
the invocation returns null.
So the TL:DR is unless you have the actual object you want you call the method on, it is not possible.
public class ClassA {
private ClassB instanceB = new ClassB();
// ...
private void sendMethod () {
Method m = ClassA.class.getMethod("foo", null);
instanceB.receiveMethod(m);
}
public void foo () {}
}
public class ClassB {
public void receiveMethod (Method method) {
Class c = method.getDeclaringClass();
}
}
gives you the owning Class. An instance doesn't own methods.
You can do this, but the proper way in your example would be the use of an interface, because that seems to be what you want: You want to pass in an object that ClassB knows how to operate on.
interface Callback {
void foo();
}
public class ClassA implements Callback {...}
public class ClassB {
public void receiveMethod(Callback cb) {...}
}
This is like asking:
"Given an apple from an Apple orchard, which tree owns this apple?"
The answer to which is:
"No idea, since all apple trees produce apples, it could belong to any tree".
... in other words - you must supply an instance from which the method will be called
EDIT
From one of your comments, I gather you are looking for an alternative of the Observer pattern. You say you don't like the messiness of the Observer pattern and that it is not "generic" enough for you.
I would argue that it is probably one of the least messiest patterns in existence, AND interfaces are by definition as generic as things get!
So, perhaps its an implementation problem you're having. Luckily, I have already posted on SO an Observer implementation in JAVA, to demonstrate how powerful and elegant it is.
Polymorphism and Interfaces in Java (can polymorphism be used to implement interfaces...why?)
In fact: reflection is messier than using an interface, since you can't guarantee at compile time that the type of Object you are invoking an instance of a Method on, even supports that method! (without some error checking code). Versus with interfaces, its not possible to even have that problem.

Categories