This question already has answers here:
Curly braces in "new" expression? (e.g. "new MyClass() { ... }")
(3 answers)
Closed 4 years ago.
we know in java that you cant create an instance of an abstract class.
but, this works:
public abstract class MyAbstract
{
int num = 10;
}
//and in main class
public static void main(String[] args) {
MyAbstract abstractObject = new MyAbstract() {};
System.out.println(abstractObject.num);
}
output:
run:
10
So we can ?
In short what is happening here ?
The syntax
new X(...) { ... }
instantiates an ad-hoc, anonymous class, extending / implementing the class / interface named X.
In your case, the abstract class has all it needs, there are no abstract methods. Therefore, the derived class doesn't need to implement any missing methods.
If you add an abstract method to your abstract class, the example will no longer work. To make it work again, you will have to implement the method in the { ... } section.
public abstract class MyAbstract
{
int num = 10;
abstract void f();
}
public static void main(String[] args) {
MyAbstract abstractObject = new MyAbstract() {
void f() {
...
}
};
System.out.println(abstractObject.num);
}
In addition, you can pass arguments to an extended base class's constructor by using the () part of the syntax:
public abstract class MyAbstract
{
MyAbstract(int argument) {
...
}
int num = 10;
abstract void f();
}
public static void main(String[] args) {
MyAbstract abstractObject = new MyAbstract(5) {
void f() {
...
}
};
System.out.println(abstractObject.num);
}
Related
I want to have a class to run other classes in java, like constructor parameterized with a class to run that class later on, similar to this
class MyClass{
Class classToRun;
public MyClass(Class c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
where classToRun possible classes doesn't have a common ancestor, but all have method someStaticMethod, and have no idea about MyClass, which runs them.
But there are problems, like inner classes cannot have static methods, classes cannot be cast Class, etc.
There are solutions for parameterized with class methods, like
How do I pass a class as a parameter in Java?
Passing a class as an argument to a method in java
but not for constructors.
What is the proper solution to do this?
Use lambdas and pass the method reference: they match on the method signature. For void someStaticMethod() you can use Runnable.
class MyClass{
private final Runnable methodToRun;
public MyClass(Runnable someStaticMethod) {
methodToRun = someStaticMethod;
}
public void runClass(){
methodToRun.run();
}
}
new MyClass(SomeClass::someStaticMethod).runClass();
You cannot enforce that the method passed has the right name, but looks even neater IMHO.
You need to understand what generics are.
interface
public interface SomeInterface {
void someStaticMethod();
}
use
class MyClass<T extends SomeInterface>{
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
As 2 of 3 answers were not to the point, I decided to publish fixed versions of both answers as far as they can be fixed.
The f1sh version from the above should like follows:
public class ClassToRunOthers {
Class classToRun;
public ClassToRunOthers(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
public static void main(String[] args) throws Exception {
ClassToRunOthers mc = new ClassToRunOthers(SomeClass.class);
mc.runClass();
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
The zwei solution above can not be fixed without reflection, as generics is not to the point. Evan if you try to parametrize not with SomeInerface (because SomeClass does not extend a common SomeInterface), but with Object, it is still won't solve the problem:
public class MyClass<T extends Object> {
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass() {
// classToRun.someStaticMethod(); // Cannot resolve method 'someStaticMethod' in 'T'
}
public static void main(String[] args) {
MyClass mc = new MyClass(SomeClass.class);
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
This can be fixed like the above, via reflection.
I believe, it can be done with annotations in some elegant way, and may be someone will share us with such a solution or I will do it by myself as time permits.
By now for myself, a solution with saving class name in the String in constructor next day after the question been asked did the trick.
You will have to use reflection if you want to execute a method when you only have the Class instance.
In the code below, runClass finds the method of the class using it's name as a String, then executes it. This code assumes that the method is static, also ignoring any Exception handling.
The following code prints "test":
class MyClass {
Class classToRun;
public MyClass(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
}
class Main {
public static void main(String[] args) throws Exception {
MyClass mc = new MyClass(Main.class);
mc.runClass();
}
static void someStaticMethod() {
System.out.println("test");
}
}
I am just learning Java concepts.
Can anyone let me know why i am not able to run this program?
package innerClasses;
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
class Inner {
public void m2() {
System.out.println(i);
}
}
}
public static void main(String[] args) {
Test t = new Test();
Test.Inner in = t.new Inner();
t.m1();
}
}
Can anyone let me know why i am not able to run this program?
The most basic reason is because of scope. In order to do
Test.Inner in = t.new Inner();
Inner must be defined in Test, but it is instead defined in m1 scope.
The class Inner is declared inside the method m1(), what makes it not available outside this method.
Your code has to look like the following to be able to run, although it will not print anything...
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
}
class Inner {
public void m2() {
System.out.println(i);
}
}
public static void main(String[] args) {
Test t = new Test();
Test.Inner in = t.new Inner();
t.m1();
}
}
Replacing t.m1(); by in.m2(); will output 10.
EDIT
In case you have to create the inner class inside the method, make it like
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
class Inner {
public void m2() {
System.out.println(i);
}
}
// this is what makes it run
Inner myInner = new Inner();
myInner.m2();
}
public static void main(String[] args) {
Test t = new Test();
t.m1();
}
}
to compile and run.
IMHO this is not a good way to go...
A method inner class is only visible to that method only so you can't use this at any other location.
for using this class you have to declare it outside of the method.
You cannot compile it as the scope of Inner class is the m1 method.
If you want to be able to create instances of Inner class you can define it directly inside the Test:
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
}
// On the Test class level
class Inner {
public void m2() {
System.out.println(i);
}
}
public static void main(String[] args) {
Test t = new Test();
Test.Inner in = t.new Inner();
t.m1();
in.m2(); // prints 10
}
}
Another feature provided by Java is to use anonymous classes. It can be created by implementation of some Interface:
// Define an interface to be able to implement it inside the method
interface Inner {
void m2();
}
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
// Implement interface and call method on it
// Functional style:
((Inner) () -> System.out.println(i)).m2();
// Legacy style:
new Inner() {
#Override
public void m2() {
System.out.println(i);
}
}.m2();
}
public static void main(String[] args) {
Test t = new Test();
t.m1(); // prints 10 twice
}
}
or extending some class:
// A class we going to extend
class Inner {
void m2() {
System.out.println(11);
}
}
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
// Extend inner class and call method on it
new Inner() {
void m2() {
System.out.println(i);
}
}.m2();
}
public static void main(String[] args) {
Test t = new Test();
t.m1(); // prints 10, not 11
}
}
So the best way for you depends on what code design do you want to get finally.
Your class Inner is what the JLS calls a Local Class (14.3. Local Class Declarations).
The scope of a Local Class is defined as (6.3. Scope of a Declaration):
The scope of a local class declaration immediately enclosed by a block (§14.2) is the rest of the immediately enclosing block, including its own class declaration.
The scope of a local class declaration immediately enclosed by a switch block statement group (§14.11) is the rest of the immediately enclosing switch block statement group, including its own class declaration.
In your case it is declared in a block, which is the body of your method. So the scope where your class is visible is the rest of this method body.
As the type Inner is not visible in main(), you cannot use it there. You could create instances of it and use them within m1(), though.
The very basic reason for compile time error is "Scope".
As per your code, class Inner is defined inside method m1 (this class is called Local class/method local class),so if you observe the scope of method variable, its within the declared method only and we cannot access any method variable outside that method and this is reason, the scope of class Inner is limited to the m1 method
so if you want to instantiate class Inner and invoke its methods then you must do it in m1 method (in code , you are trying to create class Inner object outside method m1, which is not possible) hence the code would be
public class Test {
int i = 10;
static int j = 20;
public void m1() {
int k = 30;
final int m = 40;
class Inner {
public void m2() {
System.out.println(i);
}
}
Inner in = new Inner();
in.m2();
}
public static void main(String[] args) {
Test t = new Test();
t.m1();
}
}
some more info , the local classes can be used when any repeated functionality is required inside a method (as nested methods are not allowed in java, so we can create inner class) and off course if we are not interested to create class level method for example
class Outer {
public void cal() {
class Inner {
public void sum(int x, int y) {
System.out.println("sum : "+(x+y));
}
}
Inner i= new Inner();
i.sum(10, 20); //sum is repeatdly needed in between code
i.sum(100, 200);
i.sum(1000, 2000);
i.sum(10000, 20000);
}
}
public class TestClass {
public static void main(String[] args) {
new Outer().cal();
}
}
In this class abstract class object is instantiated by overriding the getNum(), what is the purpose of this?
public abstract class AbstractTest {
public int getNum() {
return 45;
}
public static void main(String[] args) // main function
{
AbstractTest t = new AbstractTest() // From this point didn't understand
{
public int getNum() // function
{
return 22;
}
}; //use of this
System.out.println(t.getNum()); // output
}
}
The instantiation in your main() method is simply an inline class definition of a concrete instance of the abstract class AbstractTest. To be clear, the variable t is an anonymous, non abstract class instance. The following code would achieve the same thing:
public class ConcreteTest extends AbstractTest {
#Override
public int getNum() {
return 22;
}
}
public static void main (String [] args) {
ConcreteTest t = new ConcreteTest();
System.out.println(t.getNum());
}
There are instances in the course of development where it can be cumbersome to have to create a formal class definition. For example, if you only need a single instance of the abstract AbstractTest class, it would be easier to use an inline definition.
We call this 'Anonymous Class': When you need to create and use a class, but do not need to give its name or reused use, you can use an anonymous class. Here is the offical doc. Not only used for abstract class, can also be used for interface and general extensible class.
interface Base {
void print();
}
public static void main(String[] args) {
Base aInterface = new Base() {
#Override
public void print() {
System.out.println("A anonymous implement.");
}
};
Thread aThread = new Thread() {
#Override
public void run() {
super.run();
}
};
}
public interface Bsuper {
abstract class A {
abstract void test1();
void test2() {
System.out.print("test2 ");
}
}
}
// second file
public class Bsub extends Bsuper.A {
void test1() {
System.out.print("test1 ");
}
}
// third file
public class Bsubmain {
public static void main(String args[]) {
Bsub sub1 = new Bsub();
Bsuper.A obj = new Bsub();
sub1.test1();
sub1.test2();
obj.test1();
obj.test2();
}
}
It produces the output as expected test1 test2 test1 test2, but my question is in the Bsuper class, class A is static we all know that and now with the abstract keyword it becomes abstract class, but how is it possible to have both abstract and static applied to class at the same time.Is class A really static also or is there any other explanation for it.Please answer!!
how is it possible to have both abstract and static applied to class at the same time.
It is perfectly valid to have a static abstract class. This is different from having a static abstract method, which doesn't make sense, as you can't override such methods, and you're also making it abstract. But with static class, you can of course extend it, no issues. Making it abstract just restricts you with creating an instance of it.
So, even this is valid:
class Main {
static abstract class Demo { }
class ConcreteDemo extends Demo { }
}
In which case, you can't instantiate Demo, and sure you can instantiate ConcreteDemo.
Remember that a static inner class is using a different concept of static.
In this case it means that the inner class does not have access to the outer class's instance variables.
public class Test {
long n = 0;
static class A {
// Not allowed.
long x = n;
}
class B {
// Allowed.
long x = n;
}
}
Making them abstract does not change anything.
abstract static class C {
// Not allowed.
long x = n;
}
abstract class D {
// Allowed.
long x = n;
}
wondering how it is possible to call public m method?
public class Test1 {
public static void main(String[] args) {
Test1 test = new Test1() {
public void m() {
System.out.println("m");
}
};
}
}
I don't believe you can. You'd have to create an interface or subclass. (Well, okay, that's probably not true. You could probably do it with reflection.)
E.g., like this (where you call it via test.m() after construction):
public class Test1 {
public static void main(String[] args) {
SubTest1 test = new SubTest1() {
public void m() {
System.out.println("m");
}
};
test.m();
}
private static abstract class SubTest1 extends Test1 {
public abstract void m();
}
}
Or like this, where it happens during construction:
public class Test1 {
public static void main(String[] args) {
SubTest1 test = new SubTest1() {
public void m() {
System.out.println("m");
}
};
}
private static abstract class SubTest1 extends Test1 {
public SubTest1() {
this.m();
}
public abstract void m();
}
}
You can't define an anonymous class constructor, so that last uses the constructor of the SubTest1 class and the abstract method.
You cannot directly invoke m since test is of type Test1 which does not contain a method called m, but you should never find yourself in a situation like this. The whole point of anonymous classes is to alter some already-existent aspect of the base class's functionality, so adding new methods makes no sense. Consider rethinking your design or using a named class instead.
Of course, if you won't care about test in the future you could do this:
new Test1() {
public void m() {
System.out.println("m");
}
}.m();
Although you would rarely want to do something like this, it could be useful if you're working with Thread or Runnable and need to invoke the run method.
If Test1 had a method called "m" you could just call test.m() after you instantiated the inner class:
public class Test1 {
public static void main(String[] args) {
Test1 test = new Test1() {
public void m() {
System.out.println("New Behavior");
}
};
test.m();
}
public void m() {
System.out.println ("Default Behavior");
}
}
Running this would output:
New Behavior