Cannot define extra methods in an Anonymous Inner Class in Java - java

When defining extra methods (that do not override the super class methods) in an Anonymous Inner Class the code compiles fine without any issues but if I try to call the extra method it throws an error. So is it only possible to override methods in the sub class when extending with an anonymous inner class? If it is so can anyone please explain me why?
Here's what my code looks like
class SomeClass {
public static void main(String[] args) {
SomeOtherClass a = new SomeOtherClass() {
#Override
public void methodFromSuperClass() {
System.out.println("Method from super class!");
}
public void subClassMethod() {
System.out.println("Sub class method");
}
};
a.methodFromSuperClass(); //This works fine
a.subClassMethod(); // But calling this extra method throws an error
}
}
This is the error that I'm getting
SomeClass.java:20: error: cannot find symbol
a.subClassMethod();
^
symbol: method subClassMethod()
location: variable a of type SomeOtherClass
1 error

This situation is exactly the same as if the anonymous class had a name:
class SomeOtherClass {
public void methodFromSuperClass() { }
}
class Subclass extends SomeOtherClass {
#Override
public void methodFromSuperClass() {
System.out.println("Method from super class!");
}
public void subClassMethod() {
System.out.println("Sub class method");
}
}
And you did:
SomeOtherClass a = new Subclass();
a.subClassMethod();
Wouldn't you agree that you shouldn't be able to call subClassMethod here? After all, the compiler knows that a is of type SomeOtherClass, but not which subclass of SomeOtherClass it is. It doesn't analyse your code that far back to see that you actually assigned an instance of Subclass to it.
The situation with anonymous classes is basically the same. It's just that this time, the subclass doesn't have a name in your code, but it's still a subclass, and the same reasoning that "the compiler doesn't analyse your code that far back" applies.
Since the anonymous subclass has no name, you can't do something like Subclass a = new Subclass(); as in the named subclass example, but since Java 10, you can do:
var a = new SomeOtherClass() { ... };
var lets the compiler infer the type of the variable for you without you saying the type name. The compiler will infer the anonymous subclass as the type for a, and this will allow you to do:
a.subClassMethod();
Finally, it is totally allowed to declare extra members in anonymous classes - it's just rather hard to access them from anywhere other than inside the anonymous class, or the local scope, because the anonymous class has no name. Declaring extra members is still sometimes useful though, because you can access them in the overridden methods for example.

Your assumption is correct. It is not possible to call the unoverridden method this way.
Consider an example where you have declared an interface and instantiated it with a concrete class, then you still only have access to the methods defined in the interface and not in the class.
public interface MyInterface{
public void someMethod();
}
public class MyImpl implements MyInterface{
//someMethod() implementation
// ...
// newMethod()
public void newMethod(){
//some implementation
}
}
public class Main{
public static void main(String[] args){
MyInterface inter = new MyImpl();
inter.someMethod(); // this call is ok
inter.newMethod(); // this call leads to a Symbol not found Exception,
// because MyInterface has no method named newMethod...
}
}
Hope it is now clearer what is meant by this

Related

How to force my subclass constructor not to call base class constructor?

public class Base {
public Base() {
foo();
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived () {}
public void foo() {
System.out.println("Derived.foo()");
}
}
And then, when i call those:
public class Running {
public static void main(String[] args) {
Base b = new Base();
Derived d = new Derived();
}
}
It outputs:
*Base.foo()*
*Derived.foo()*
So why, when it gets to derived constructor, it invokes the base constructor but uses the derived's method instead?
PS: If I mark those methods as private, it will print out:
*Base.foo()*
*Base.foo()*
This is how Java works read this page https://docs.oracle.com/javase/tutorial/java/IandI/super.html
And more specifically the Note here :
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
So as you can see this is expected behavior. Even though you dot have a super call it is still automatically inserting it.
In regards of the second Question even though you are within the super constructor body still you Instance is of the Subtype. Also if you have some familiarity with C++ read this Can you write virtual functions / methods in Java?
The reason why it will write the base class when marking with private is because private methods are not Inherited. This is part of the Inheritance in Java topic.
To answer the question in your title. As I said, you cannot avoid the base class constructor being called (or one of the base class constructors if it has more than one). You can of course easily avoid the body of the constructor being executed. For example like this:
public class Base {
public Base(boolean executeConstructorBody) {
if (executeConstructorBody) {
foo();
}
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived() {
super(false);
}
public void foo() {
System.out.println("Derived.foo()");
}
}
public class Running {
public static void main(String[] args) {
Base b = new Base(true);
Derived d = new Derived();
}
}
Now the main method prints only:
Base.foo()
Because in the contructor of the Derived class it automatically gets injected a call to super(), if you do not add a call to super or to other constructor in the same class (using this).

Clarification on Interface concept

interface A
{
public void printValue();
}
public class Test
{
public static void main (String[] args)
{
A a1 = new A() {
public void printValue()
{
System.out.println("A");
}
};
a1.printValue();
}
}
We cannot create an instance of an interface, but what is new A() doing in this code? I have seen this type of code used mostly with Comparators. Please explain.
new A() {} is an instantiation of an anonymous class that implements interface A.
It is a short-cut that can be useful if you need an instance of a class that implements an interface only in one place, so you don't want to define a normal class. This way you define the class at the same place it is being used.
In your code sample, it doesn't seem very useful, but usually it is used by passing the anonymous class instance to some method that accepts a parameter of the type of the interface.
new A() in below is where you are instantiating a concrete class (which we say anonymous) which implements the interface A
A a1 = new A() {
public void printValue(){
System.out.println("A");
}
};
In your code, interface A is used as an Anonymous class. You can use them if you need to use a local class only once. it's more over same as lambda expressions.
Read more: http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
Read about lambda expression: http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

How to do a one-time operation under abstract class

I am developing a webApplication based on Java EE.
I have an abstract class, in which I need to have a one-time operation (a database call).
So below in the sample code, I pasted it inside its constructor, but don't know why the constructor is not getting invoked.
Please tell me how to solve this.
public abstract class Preethi {
Preethi()
{
System.out.println("hirerew");
}
public static void main(String args[])
{
int a = 12;
if(a==0)
System.out.println("a");
if (a==12)
System.out.println("12");
}
}
You never create an instance of abstract class Preethi. Why do you expect the constructor to get called? Make a non-abstract subclass and create an instance of it and then the constructor will be called. main is static, it can be called without Preethi being realized.
public class X extends Preethi
{ /* Your implementation here */}
Then in main:
public static void main(String [] args)
{
Preethi preethi = new X(); // This will call the constructor of Preethi
}
Constructor is not being invoked because main() method is called without instantiating a main class.
To invoke it - you need to create an object of Preethi explicitly.
UPD. as anio suggests - you need to subclass Preethi and instantiate it.
Although abstract classes cannot be used to instantiate objects, they can be used to create object references, because Java's approach to run-time polymorphism is implemented through the use of superclass references. Thus, it must be possible to create a reference to an abstract class so that it can be used to POINT TO A SUBCLASS object.
You can make it not abstract, or create a subclass that invokes super() on your abstract class.
See the code below:
public abstract class Preethi {
// constructor:
Preethi() {
System.out.println("hirerew");
}
public static void main(String[] args) {
// call the constructor:
new Preethi() {}; // "{}" needed because our class is abstract.
}
}
The point here is that you don't always have to create a new class, but can define a 'one-time' class next to the constructor. For example:
public abstract class A {
public abstract void foo();
public A() { foo(); }
}
You could do the following:
A a = new A() {
public void foo() {
System.out.println("hello");
}
};
The output would simply be "hello". A similar method could also be utilized for interfaces.
You are not creating object of Preethi. In order to make call to constructor, You have to remove abstract keyword from class and create it's object
Or create anonymous inner class and it's object as :
new Preethi() {
// abstract method impl
};
Or create sub class of Preethi, and create object of it.
FYI: You can create object references of any abstract class or interfaces. You can not create object of them.
And I think making main class abstract really does not make any sense. Atlease to me.(Tell me if I am wrong)

Java: get the class of the inherited class from a static method

I have the following problem in Java:
I have a base class and a derived class and I have a method in the base class. When I call the Base's foo method through Derived I want to get the Derived's class. The foo method can be generic if it can be done that way.
class Base
{
static void foo()
{
// I want to get Derived class here
// Derived.class
}
}
class Derived extends Base
{
}
Derived.foo();
Thanks for your help!
David
That's not the way that static methods work. You'll have to implement Derived.foo(), do whatever it is that's special to Derived, and that method then calls Base.foo(). If you really need the type information, you could create Base.foo0(Class klass).
But to be honest, any static method that needs to know that type of the class that it's invoked on should probably be an instance method.
Well, the caller of Derived.foo() knows what they are calling, so you could alter your methods thus:
class Base
{
static void foo(Class< T > calledBy)
{
// I want to get Derived class here
// Derived.class
}
}
class Derived extends Base
{
}
Derived.foo(Derived.class);
static methods are not inheritated. Static methods with the same signature can only hide similar methods in the superclass. This means that you never will see the result you probably want - you always exactly know the enclosing class. It is never possible that the static method is somehow "within" another class. So it is just impossible to produce the desired result. Calling a static method from a subclass or an instance is a bad idea for this reason as it just hides the real class. (IDEs and static code analysis tools can mark or correct this.)
Sources:
JLS http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#227961
http://docs.oracle.com/javase/tutorial/java/IandI/override.html
So what works with inherited methods does not work with static methods that are not inherited.
class Base {
static void foo() {
// Only the static context is available here so you can't get class dynamic class information
}
void bar() {
System.out.println(getClass());
}
}
class Derived extends Base {
}
class Another extends Base {
static void foo() {
// No super call possible!
// This method hides the static method in the super class, it does not override it.
}
void bar() {
super.bar();
}
}
Derived derived = new Derived();
derived.bar(); // "class Derived"
Base base = new Base();
base.bar(); // "class Base"
// These are only "shortcuts" for Base.foo() that all work...
derived.foo(); // non-static context
Derived.foo(); // could be hidden by a method with same signature in Derived
base.foo(); // non-static context
Base.foo(); // Correct way to call the method
Another a = new Another();
a.foo(); // non-static context
Another.foo();
Is it good idea that the language allows this? - Hm. I think it is telling that IDEs and code analysis tools warn and can even correct this automatically.
Not possible, Derived.foo() will simply give code for Base.foo().
Derived.foo();
This will go to foo defined in Derived, if one is defined there:
class Base {
static void foo() {
System.out.println("Base");
}
}
class Der extends Base {
static void foo() {
System.out.println("Der");
}
}
class Check {
public static void main(String[] args) {
Base.foo();
Der.foo();
}
}
When I run it:
javac -g Check.java && java Check
Base
Der
So what is your question? If you to require that each derived class implement foo that is not possible to enforce in Java.

Overriding a method

public class Testing extends JDialog {
public MyClass myClass;
public Testing() {
}
}
given the above code, is it possible to override a method in myClass in Testing class?
say myClass has a method named computeCode(), will it be possible for me to override it's implementations in Testing? sorry it's been a long time since I've coded.
if you want to override a method from MyClass then your testing class must extend that. for overriding a method one must complete IS-A relationship whereas your code comes under HAS-A relationship.
Yes, it is generally possible (note that as others have correctly mentioned - you'd need to extend it to override the method). Refer to this sample:
public class Animal {
public void testInstanceMethod() {
System.out.println("The instance method in Animal.");
}
}
public class Cat extends Animal {
public void testInstanceMethod() {
System.out.println("The instance method in Cat.");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
myAnimal.testInstanceMethod();
}
}
Not only is it possible, but it is a key feature in polymorphism an code reusability.
Note, however, that MyClass.computeCode might be final - in this case, it cannot be overridden.
You override methods of classes that you extend. Therefore, in your example your Testing class could override the various existing methods of JDialog. If you wanted to override computeCode() from MyClass (assuming it's not final), you should make Testing extend MyClass.
public class Testing extends MyClass
{
#Override
public int computeCode()
{
return 1;
}
}
You can override a class's method only in a subclass (a class that extends the class whose method you want to override). However, given your skeletal code, you can (within Testing) have a nested class that extends MyClass and force an instance of that nested class into the myClass instance variable... so, the answer must be "yes".
Whether that's the best choice (as opposed to using interfaces, rather than subclassing concrete classes, and relying on Dependency Injection to get the implementations most suited for your testing), that's a different question (and my answer would be, unless you're testing legacy code that you can't seriously refactor until it's well test-covered... then, probably not;-).
See, if you want to override method from MyClass then you need to extend it.
As per your code, it seems you want to make a wrapper wround MyClass.
Wrapper means, calling implemented class method will call method of MyClass.
I am just clearing how wrapping works as below.
public class Testing extends JDialog {
public MyClass myClass;
public Testing() {
}
public void someMethod() {
//Add some more logic you want...
...
..
myClass.computeCode();
}
}
thanks.
The wording of the question is confused and lost.
Here are some key points:
You can't #Override something that you didn't inherit to begin with
You can't #Override something that is final
Here's a small example:
import java.util.*;
public class OverrideExample {
public static void main(String[] args) {
List<String> list = new ArrayList<String>(
Arrays.asList("a", "b", "c")
) {
#Override public String toString() {
return "I'm a list and here are my things : " + super.toString();
}
};
System.out.println(list);
// prints "I'm a list and here are my things : [a, b, c]"
}
}
Here, we have an anonymous class that #Override the toString() method inherited from java.util.ArrayList.
Note that here, it's not class OverrideExample that overrides the ArrayList.toString(); it's the anonymous class that (implicitly) extends ArrayList that does.
All the above answers are valid. But, if you want to extend JDialog but still if you want to override a method of another class it is possible through interfaces. Interfaces won't have method definitions but will have method declarations. More about interfaces, you can read at http://java.sun.com/docs/books/tutorial/java/concepts/interface.html
In your case, you can make use of interface like this
public interface MyInterface{
public void myMethod();
}
public class Testing extends javax.swing.JDialog implements MyIterface{
public void myMethod(){
// code for your method
}
}
Since Testing class has already inherited JDialog, there is no way let it inherit MyClass again unless to implement an interface. What you can do is to use some design pattern. However this is not overriding, since there is no inheritance. The Adapter is the one you need. Again you are losing the flexibility of polymorphism.
public class Testing extends JDialog {
MyClass myClass = new MyClass();
public Testing() {
}
public void methodA(){
myClass.methodA();
}
}
class MyClass {
public void methodA(){}
}

Categories

Resources