Lets assume I have class:
class A {
protected int x; // no public getter, setter
}
Now I want to extend class A, to overwrite 'x' variable. The answer would be:
public class SomeClass {
someMethod() {
A extendedClass = new MyExtension(5);
}
class MyExtension extends A {
public MyExtension(int x) {
super.x = x;
}
}
}
And my question: is there any possibility to do it without defining nested class separately? I mean something like this
someMethod() {
A extendedClass = new A() {
// here do something like super.x = 5;
}
}
I tried with Calling newly defined method from anonymous class but it won't let me instantiate A class. Also I dont want to use reflection.
I simpy dont want to define nested class just to overwrite one property. Origin of the problem is Spring-integration ImapMailReceiver, where I want to overwrite task scheduler. Like below:
final ImapMailReceiver imapMailReceiver = new ImapMailReceiver() {
super.setTaskScheduler(MYTASKSCHEDULERHERE);
}
Your new A() { ... } still is just defining a new class. Thus, you cannot simply put any statement between the curly brackets, only field, method and nested type declarations may go there, but constructors are not allowed. You may add an instance initializer instead:
A extendedClass = new A() {
{
x = 5;
}
}
Why to use nested or anonymous inner class?
We can do overriding and access the overrided variable as below.
public class SomeClass extends A{
int val;
void someMethod(int val) {
super.x = val;
}
public static void main(String[] args) {
SomeClass sc = new SomeClass();
System.out.println(sc.x); // output=10
sc.someMethod(20);
System.out.println(sc.x); // output=20
}
}
class A {
protected int x = 10; // no public getter, setter
}
Related
What did I do wrong here? Need to print -1 and 100 but I keep getting this error:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
No enclosing instance of type Main is accessible. Must qualify the allocation with an enclosing instance of type Main (e.g. x.new A() where x is an instance of Main).
at Main.main(Main.java:3)
public static void main(String[] args) {
MyClass a = new MyClass();
MyClass b = new MyClass(100);
System.out.println(a.getValue()); // -1
System.out.println(b.getValue()); // 100
}
public class MyClass {
private int value;
// Constructors
public MyClass() {
value = -1;
}
public MyClass(int x) {
value = x;
}
public int getValue() {
return value;
}
}
}
Your problem is that your main method has no class. Here you have an example:
public class Main {
public static void main(String[] args) {
MyClass a = new MyClass();
MyClass b = new MyClass(100);
System.out.println(a.getValue()); // -1
System.out.println(b.getValue()); // 100
}
}
class MyClass {
private int value;
// Constructors
public MyClass() {
value = -1;
}
public MyClass(int x) {
value = x;
}
public int getValue() {
return value;
}
}
You can also create some inner classes, as explained here: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
But, if you are starting as a programmer, I don't recommend you to create neither inner nor outer classes, and rather create a new class. Something like:
org.demo.myclasses.Main ==> This is your Main class with your main method.
org.demo.myclasses.MyClass ==> Another different file for your new class.
Here's another question made by another user with more info about it: Java inner class and static nested class
While making a small game in Java, I stumbled upon the keyListener class, which asks for three methods when instanced (keyTyped, keyPressed, and keyReleased), as below:
JFrame.addKeyListener(new KeyListener(){
public void keyTyped(KeyEvent evnt) {
//blah
}
public void keyPressed(KeyEvent evnt) {
//blah
}
public void keyReleased(KeyEvent evnt) {
//blah
}
});
How can I get a class I am making on my own accept methods as a parameter as above?
new KeyListener() { ... } actually creates an anonymous inner class that implements KeyListener. As such it can access any visible field of the class that created it as well as any local final variable inside the method that called the constructor.
Example:
class Outer {
int x;
void initUI( final int z) {
final int y = 0;
int nope = 1; //you can't access this since it is neither final nor a field like x
JFrame.addKeyListener( new KeyListener() {
public void keyTyped(KeyEvent evnt) {
System.out.println( x + y + z ); //you can access all of them
}
});
}
}
If you want to provide a constructor for your key listener you'll need to explicitly define a class, as anonymous classes can't have custom constructors. That means you'd have to do something like this (attention: pseudo code):
class Outer {
void initUI() {
JFrame.addKeyListener( new InnerKeyListener( myParam ) );
}
class InnerKeyListener implements KeyListener {
InnerKeyListener( Param p ) {
}
...
}
}
Of course you can put the inner class into a separe file as well or make it a static inner class.
Technically, those methods aren't parameters here. The only parameter is the one anonymous instance of a KeyListener.
KeyListener is an interface that requires those 3 methods to be implemented.
If you want to define your own interface, it looks similar to a class:
public interface SomeInterface {
public void foo();
public int bar(int x);
}
Then you can use it anonymously (like in your example), or by implementing it in a class:
public class MyClass implements SomeInterface {
// ...
}
It's not accepting methods as a parameter. You're declaring an anonymous class and passing that as a parameter into the addKeyListener method.
I know that it is weird to answer my own question, but...
I figured it out. You have to make your class abstract, and you can declare abstract methods to make methods "parameters" to have it behave like a KeyListener declaration. Abstract methods are declared like this:
abstract ReturnType name(Parameter p);
and behave exactly like methods when called. For a full example:
//The abstract keyword enables abstract methods to work with this class.
abstract class Foo {
//Just a random variable and a constructor to initialize it
int blah;
public Foo(int blah) {
this.blah = blah;
}
//An abstract method
abstract void doStuff();
//Example with a parameter
abstract void whatDoIDoWith(int thisNumber);
//A normal method that will call these methods.
public void doThings() {
//Call our abstract method.
doStuff();
//Call whatDoIDoWith() and give it the parameter 5, because, well... 5!
whatDoIDoWith(5);
}
}
When you try to instance an abstract class like a normal class, Java will freak out.
Foo f = new Foo(4);
What you will have to do is something like this:
Foo f = new Foo(4) {
#Override
void doStuff() {
System.out.println("Hi guys! I am an abstract method!");
}
#Override
void whatDoIDoWith(int thisNumber) {
blah += thisNumber;
System.out.println(blah);
}
}; //Always remember this semicolon!
Note that you need to include all of the abstract methods here, not just some of them. Now, let's try this:
public class Main {
public static void main(String[] args) {
//Instance foo.
Foo f = new Foo(4) {
#Override
void doStuff() {
System.out.println("Hi guys! I am an abstract method!");
}
#Override
void whatDoIDoWith(int thisNumber) {
blah += thisNumber;
System.out.println(blah);
}
};
//Call our method where we called our two abstract methods.
foo.doThings();
}
}
This prints the following to the console:
Hi guys! I am an abstract method!
9
I tried this:
class protectedfinal
{
static abstract class A
{
protected final Object a;
}
static class B extends A
{
{ a = new Integer(42); }
}
public static void main (String[] args)
{
B b = new B();
}
}
But I got this error:
protectedfinal.java:12: error: cannot assign a value to final variable a
{ a = new Integer(42); }
^
1 error
How to work around this problem?
Some people suggested here to use a constructor but this works only in some cases. It works for most objects but it is not possible to reference the object itself from within the constructor.
static abstract class X
{
protected final Object x;
X (Object x) { this.x = x; }
}
static class Y extends X
{
Y () { super (new Integer(42)); }
}
static class Z extends X
{
Z () { super (this); }
}
This is the error:
protectedfinal.java:28: error: cannot reference this before supertype constructor has been called
Z () { super (this); }
^
One could argue that it does not make much sense to store this kind of reference, because this exists already. That is right but this is a general problem which occurs with any use of this in the constructor. It is not possible to pass this to any other object to store it in the final variable.
static class Z extends X
{
Z () { super (new Any (this)); }
}
So how can I write an abstract class, which forces all child classes to have a final member which gets initialized in the child?
You have to initialize A.a in its constructor. Subclasses will use super() to pass initializer to A.a.
class protectedfinal {
static abstract class A {
protected final Object a;
protected A(Object a) {
this.a = a;
}
}
static class B extends A {
B() {
super(new Integer(42));
}
}
public static void main (String[] args) {
B b = new B();
}
}
You cannot use this until superclass constructors were called, because at this stage the object is not initialized, even Object constructor hasn't run at this point, therefore calling any instance methods would lead to unpredictable results.
In your case, you have to resolve circular reference with Z class in another way:
Z () { super (new Any (this)); }
Either use a non-final field or change class hierarchy. Your workaround with instance method super(new Any(a())); would not work for the same reason: you cannot call instance methods until superclass constructors were run.
In my personal oppinion, your problems hints towards a flaw in design.
But to answer your question. If absolutly necessary, you can change final fields in java using reflection.
And if everything fails, you can still utilize sun.misc.unsafe.
But I strongly discourage you from doing so, since it potentially kills your vm.
My work around so far is to use methods instead of final members:
class protectedfinal
{
static abstract class AA
{
protected abstract Object a();
}
static class BB extends AA
{
#Override
protected Object a() { return this; }
}
public static void main (String[] args)
{
AA a = new BB();
System.out.println (a.a());
}
}
But I would like to use final members, because I think accessing a final member is faster than calling a method. Is there any chance to implement it with final members?
If we have class A & B, and class A's constructor is private, and we want to use an instance of A in B, how to do that ? I see an answer that says "provide a static method or variable that allows access to an instance created from within the class " but I didn't understand that.
The code pattern you seek is called the Factory Method.
The class provides a static method that returns an instance of its own class. Private constructors are visible to all methods (including static ones) of the class, so the static method can invoke the private constructor on the caller's behalf.
Here's an example of this pattern in action:
public class A {
private A() {
}
public static A create() {
return new A();
}
}
This is often employed in conjunction with the Singleton Pattern, which would change the above example to this:
public class A {
private static A INSTANCE = new A();
private A() {
}
public static A getInstance() {
return INSTANCE;
}
}
A needs to have a public method that provides an instance of the class A, eg:
class A {
/*Constructors and other methods omitted*/
public static A getInstance() {
return new A();
}
}
Alternatively, if B is an inner class of A (or vice-versa), then B can directly reference the constructor eg:
public class A {
private A() {}
public static class B {
private A instanceOfA = new A();
public B() {}
}
}
A class that only has private constructors is designed so that other classes cannot instantiate it directly. Presumably there is a sound reason for this. The class may provide a factory method for instantiating the class ... or getting an existing instance of the class.
If you need to change the design, the best way is to modify the class; e.g. by making a constructor visible, or by adding a factory method. If you can't do that, I think it is possible to use reflection to break the visibility rules and create an instance using a private constructor. However, I'd only do this as a last resort ... and not before carefully analysing the consequences for the overall application.
Private constructors are intended to make a class not to have any instance. But the content can be accessed from child class using super(). Implementation is like this:
public class ClassA {
private int val;
private ClassA(int val)
{
this.val = val;
}
public int getVal() {
return val;
}
}
public class ClassB extends ClassA {
public ClassB(int val) {
super(val); } }
...
ClassB b = new ClassB(4);
System.out.println("value of b: " + b.getVal());
As an example see class Calendar. To get an instance you must not call its constructor but use a static method:
Calendar rightNow = Calendar.getInstance();
source
public class Test {
public static void main(String[] args) {
DemoAbstractClass abstractClass = new DemoAbstractClass() {
private String val;
#Override
public void runner() {
val = "test";
System.out.println(val);
this.run();
}
public String getVal() {
return val;
}
};
abstractClass.runner();
/**
* I want to access getVal method here
*/
}
}
abstract class DemoAbstractClass {
public void run() {
System.out.println("running");
}
public abstract void runner();
}
Here, I'm declaring an abstract class DemoAbstractClass. I can obviously create a new class that extends this class and add this method to it. But, I would prefer not doing that in my scenario.
Is there any other way to access getVal method in above code??
You can't. You need to make a proper (non-anomous) class out of it. Make it an inner private class if you want to limit its scope.
Alternatively, you could use a StringBuffer and share a referense to it between the methods. Not extremely clean however.
Related question:
Accessing inner anonymous class members
Short of using reflection, you cannot as you have no access to the concrete type of the object to be able to bind the methodcall to
If you don want to do something like this in a sane manner, declare a named class and use that as the type of abstractClass
Unfortunately, if you cannot name the type, you cannot access the methods at the language level.
What you can do, though, is use the reflection API to get a Method object and invoke it on this object.
This, however, is pretty slow. A private class or private interface would be much faster.
I can obviously create a new class that extends this class and add this method to it.
You've already done this; the end result was an anonymous inner class: new DemoAbstractClass() { ... }; If you just moved that declaration into its own class -- you can even make it a private class -- you can access getVal.
Per your example above:
public class Test {
public static void main(String[] args) {
DemoClass abstractClass = new DemoClass();
abstractClass.runner();
/**
* I want to access getVal method here
*/
abstractClass.getVal(); // can do this here now
}
private class DemoClass extends DemoAbstractClass {
private String val;
#Override
public void runner() {
val = "test";
System.out.println(val);
this.run();
}
public String getVal() {
return val;
}
}
}
}
Another option is to make a StringBuilder a member of the main method and use the closure nature of anonymous inner methods:
public static void main(String[] args) {
final StringBuilder value = new StringBuilder();
DemoAbstractClass abstractClass = new DemoAbstractClass() {
#Override
public void runner() {
value.append( "test" );
System.out.println(val);
this.run();
}
};
abstractClass.runner();
// use val here...
String val = value.toString();
}