This question already has an answer here:
Making the inner class of a generic class extend Throwable [duplicate]
(1 answer)
Closed 3 years ago.
I did notice a weird behaviour about the static and non-static inner exception classes.
For example the below code will not compile:
public class MyClass<T> {
private class MyInnerException extends Exception { // won't compile
..
}
}
But the below code will compile:
public class MyClass<T> {
private static class MyInnerException extends Exception { // will compile
..
}
}
Why is this behaving this way?
One thing is for sure that we cannot have Generic exceptions due to type erasure but then the above is not a Generic exception class but it is inside the Generic class. But if it is static it is allowed but if it is non-static it is not allowed?
Follow up question, is generic exception not allowed just because of the type erasure feature of Generic like it mentioned here:
https://www.mscharhag.com/java/java-exceptions-and-generic-types
Or there is some other reason to it?
One thing is for sure that we cannot have Generic exceptions due to type erasure but then the above is not a Generic exception class but it is inside the Generic class.
Your inner class (the first snippet) is a generic class, since its enclosing class is a generic class, and the enclosing class is part of the inner class. You cannot create an instance of an inner class without a corresponding instance of the enclosing class.
As to why generic classes cannot extend Exception:
It is a compile-time error if a generic class is a direct or indirect subclass of Throwable (§11.1.1).
This restriction is needed since the catch mechanism of the Java Virtual Machine works only with non-generic classes.
(JLS 8.1.2)
i.e. catch clauses cannot distinguish between MyClass<String>.MyInnerException and MyClass<Integer>.MyInnerException, and therefore generic exception classes are not allowed.
Related
This question already has answers here:
Why would a static nested interface be used in Java?
(11 answers)
Closed 4 years ago.
I would think this is easily googleable question, but I found nothing. In the following code:
public class ParentClass {
public static interface InterfaceStatic {
}
public interface InterfaceNotStatic
{
}
}
Can you describe the difference between InterfaceNotStatic and InterfaceStatic? I know what the same syntax means for nested classes, but since interfaces hold no value, the purpose of static here eludes me.
Both declarations are the same. The static modifier is redundant in this case.
A member interface is implicitly static (§9.1.1). It is permitted for the declaration of a member interface to redundantly specify the static modifier.
(quote from JLS 8.5.1. Static Member Type Declarations)
Static inner interface and inner interface is the same, all access rules are the same as with inner static class. So inner interface can be accessible only if you have access to its parent class/interface. In case below you will have access to interface B only from package of interface A, because A has default access modifier. BTW: interface B could be static or not.
I am trying to find out, if it is possible to create anonymous inner class as abstract. I thought, that it doesn't make sense because I am trying to create instance of the abstract class, but the message from compiler confused me:
Class 'Anonymous class derived from Test' must either be declared abstract or implement abstract method 'method()' in Test
Code:
abstract class Test{
abstract void method();
}
Test o = new Test(){};
If it is possible to declare anonymous class as abstract, please let me know how to do that.
I would be greatful for answer.
See JLS Sec 15.9.5 (emphasis mine):
15.9.5. Anonymous Class Declarations
An anonymous class declaration is automatically derived from a class instance creation expression by the Java compiler.
An anonymous class is never abstract (§8.1.1.1).
An anonymous class is always implicitly final (§8.1.1.2).
An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1).
you can't and does not make sense to declare anonymous class as abstract class as anonymous are used as local class only once.
i think you are getting this error because of similar issue Class must either be declared abstract or implement abstract method error
As quoted by Andy Turner the answer to your question is NO.
However I think you wanted to know something different.
Why do you get this compiler message?
Well the compiler is a bit misleading here. It offers two possible solutions based on that you are declaring a class (that anonymous class) and then also want to create an instance of that class:
make the derived class (which an anonymous class always is) abstract,
this is fine for normal and inner classes but it is not possible for anonymous classes, so the compiler should not suggest it in the first place
implement all methods and have no abstract methods in your anonymous class declaration
So to solve your actual problem: simply implement method() so your anonymous class declaration contains no more abstract methods
abstract class Test{
abstract void method();
}
Test o = new Test()
{
void method()
{
// do something
};
};
Now everything is declared and the compiler should not complain any more.
The following won't compile:
class Outer<T> {
class Inner {
}
static class Nested {
Inner inner; // Error: Outer.this cannot be referenced from a static context
}
}
However, if I remove <T>, it compiles. Why the inconsistency?
Also, if I say Outer.Inner inner;, instead of Inner inner;, it compiles. Again, why the inconsistency?
I'd expect an error in either all cases or none. Could anyone explain what's going on?
Why the inconsistency?
I would say this is not inconsistency at all. This is basically a problem of understanding of generics. Consider the following code (Your modified code):
class Outer<T> {
class Inner{
T t;//Added this extra line
}
static class Nested {
Inner inner;
}
}
In this above example is somewhat similar to what you have written only I have added a new variable t of type T which is the generics of Outer class in the class Inner. Now in this above example would not compile because there is a non-static or runtime reference present in the Inner class, so, when you declare Inner in a static class Nested the JAVA complier does not know the type of T, which is only declared in the runtime, so you get an error. But in your case you have done nothing like that but still the compiler does not know whether something like that is present or not. So it gives the error.
Now in the second case you have removed the generic T from the class declaration of the Outer. So there is no possibility of declaring variable t in the Inner class so there is no error.
In the third case you declared Outer.Inner for the type of variable inner and it compiled successfully. Here the compiler considered Outer as RAW TYPE. But this type of raw type declarations should be avoided. So it would be better to write:
Outer<?>.Inner inner;
Here Java compiler considers Outer to take any object as parameters which would inherit Object.
class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
Static Nested Classes
As with class methods and variables, a static nested class is associated with its outer class. And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class: it can use them only through an object reference.
Static nested classes are accessed using the enclosing class name:
OuterClass.StaticNestedClass
For example, to create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
For more information see the below click:
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
This question already has answers here:
Static method in a generic class?
(12 answers)
Closed 8 years ago.
I'm new to generics, and am struggling with applying to my situation:
I currently have several SyncData Classes, one for each object type that I wish to sync. I'm looking at changing this to a single generic class SyncData. Within this class some parts of the code will use objects of type T, but I'd also like to reference static Methods of type T. This would enable me for example to specify a notification action (specific to the data type) to be called on completion of the sync.
I'm getting myself caught in a loop: to access the methods I need to define an interface that all the types will implement, in the generic T extends interface, and then I can reference the relevant methods of type T within my generic SyncData Class. However I can't specify a static method in an interface, and because I can't in the interface, I cant access it in my generic SyncData Class.
I've looked at various tutorials, questions here etc, maybe I'm missing the obvious, but I can't see the way forward - everything that comes up seams to refer to different issues with generics and static nethods. Any advice would be very much appreciated.
Edit:
As requested some sample code added to illustrate what I tried to do (I'm actually looking to use static methods at various other points within the code, but this illustrates the point).
Is it possible to access the static method of class T from within the SyncAction class (without making T extend DataType1 by which point there is no point using generics as T cannot be DataType2)?
public interface Syncable {
//following needed or I can't access onSyncComplete in SyncAction
public void onSyncComplete();
}
public class DataType1 implements Syncable {
//constructor etc removed as irrelevant to question
//Eclipse warns 'this static method cannot hide instance method from Syncable'
public static void onSyncComplete(){
//do stiff here
}
}
public class SyncAction<T extends Syncable>{
//do all the syncing etc using multiple DataType1 objects
T.onSyncComplete();
}
Even though the onSyncComplete() method could be static, you must make them instance (ie non-static) methods for this to work.
The reason is that static methods (and fields) are not "inherited".
If you really want to have a static method, you could have your onSyncComplete() instance method call another (perhaps private) static method in its implementation.
Few things:
Eclipse is correct in stating that your static version of onSyncComplete() is incorrect. From JLS seciton 8.4.8.2:
It is a compile-time error if a static method hides an instance method.
In this case, your static method is hiding the instance method defined in your interface, so you get an error.
This is because if such a thing were allowed there would be some ambiguity as to whether the static method or instance method were to be called, as you can invoke static methods on an instance (although that isn't really a good idea for readability, and is considered a mistake by some).
The reason you cannot call static methods on a generic type is that static methods are bound at compile time. Because generic types are erased during compilation to their bounding type (Syncable in your case), the compiler will not be able to figure out which static method to bind, and so emits an error.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why doesn’t Java allow generic subclasses of Throwable?
I'm trying to make a regular RuntimeException inside a generic class like this:
public class SomeGenericClass<SomeType> {
public class SomeInternalException extends RuntimeException {
[...]
}
[...]
}
This piece of code gives me an error on the word RuntimeException saying The generic class SomeGenericClass<SomeType>.SomeInternalException may not subclass java.lang.Throwable.
What has this RuntimeException to do with my class being generic?
Java doesn't allow generic subclasses of Throwable. And, a nonstatic inner class is effectively parameterized by the type parameters of its outerclass (See Oracle JDK Bug 5086027). For instance, in your example, instances of your innerclass have types of form SomeGenericClass<T>.SomeInternalException. So, Java doesn't allow the static inner class of a generic class to extend Throwable.
A workaround would be to make SomeInternalException a static inner class. This is because if the innerclass is static its type won't be generic, i.e., SomeGenericClass.SomeInternalException.
public class SomeGenericClass<SomeType> {
public static class SomeInternalException extends RuntimeException {
[...]
}
[...]
}