This question already has answers here:
Declaring a method when creating an object
(4 answers)
Can I access new methods in anonymous inner class with some syntax?
(7 answers)
Override method, why can't I referenciate new own methods?
(2 answers)
Closed 3 years ago.
i was trying to create an anon class in java
class myClass {
int x = 10;
}
public class Main {
public static void main(String[] args) {
myClass myObject = new myClass() {
public void run(){
System.out.println(x);
}
};
myObject.run(); //gives an error saying "method run() is undefined for the type myClass"
}
}
and it does not seem to work at all , it gives me an error saying that method run() is undefined although i created an anon class containing the run() mehtod , i am a complete java beginner , i code most of the time in javascript , javascript is the language i am most familiar with and i am trying to get used to java concepts so yeah this question might seem silly to alot of people here and i apologize for that.
thanks in advance
This is because the compiler doesn't know there is a run method, because there isn't one on the base class myClass.
This would work in Java 10+, using var:
var myObject = new myClass() {
public void run(){
System.out.println(x);
}
};
myObject.run();
This works because myObject isn't exactly a myClass, but is actually specifically the anonymous class, which is called something like TheContainingClass$1 (where TheContainingClass is the name of the class in which this code appears).
It's a bit weird because you can't actually refer to this class by name - only with var!
Or, in earlier versions of Java, it works if you don't assign it to a variable:
new myClass() {
public void run(){
System.out.println(x);
}
}.run();
Again, this works because the receiver of the run() call has the type of the anonymous class, not myClass; but there is just no way in pre-Java 10 to declare a variable of that type.
The error occurs since your compiler is unaware of the method run()
You could fix it by making myClass an interface, or by using an abstract method.
abstract class myClass{
int x = 10;
public abstract void run();
}
If you use
interface myClass{
public void run();
int x = 10;
}
It should run. The problem here is that you don't have the run method in myClass declaration
Related
This question already has answers here:
:: (double colon) operator in Java 8
(17 answers)
Closed 2 years ago.
I have a class constitues 2 methods static and non static respectively, as per my limited knowledge submit method accepts runnable,callable instance directly or through lamba expression.
Today I came to know that we can even call or trigger static as well as non static method directly by using double colon which has been added in java 8.
I was just wondering how this works, there is no run method in my class and it doesn't implements runnable and even I'm not using lamba?
Is it a good practice to use :: or one should pass the runnable or callable instance.
Is there any other way to call a method inside submit() rather passing an instance?
Class A {
public static void printSomething(){
System.out.println("Staitc Method");
}
public void print()
{
System.out.println("Non-Staitc Method");
}
}
psvm()
{
A a = new A():
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(A::printSomething); //Expected is runnable or callable task
es.submit(a::print);
}
A::printSomething is called a method reference. When you use a method reference in a place that expects an interface like Runnable or Callable, Java automatically creates an implementation of that interface that calls the method.
That is,
es.submit(A::printSomething);
behaves the same as
es.submit(new Runnable() {
public void run() {
A.printSomething();
}
});
but is easier to read and does not create a new class everywhere you use it, or a new object instance every time it's called.
You can read more about method references in
The tutorial from Oracle
This write-up on Baeldung
Another way of achieving the same is using lambda expressions such as:
es.submit(() -> A.printSomething());
Since Runnable is a functional interface, you can use lambda expressions or method references that fit it even if the method name doesn't match. Therefore any no-arg void method can be used as a Runnable.
Runnable r1 = () -> a.printSomething();
Runnable r2 = A::printSomething(); // Method reference, short-hand
Runnable r3 = () -> A.printSomething(); // Same as r2, but as explicit lambda expression
The reason why the method reference works even though the class does not implement a void run() method is because what matters for Functional Interface assignment is the method signature and not the method names.
The method signature of A's printSomething matches Runnable's run and for that reason it works. Notice this only works with Functional Interfaces (i.e. those with only one method, said method method not having a default implementation).
Is it good practice? It's a matter of style but it is definitely not bad practice to use method references, and they're also more concise than left -> right lambdas.
I suggest you try this out yourself so you're clear on the rules.
public class FunctionalInterfaceDemo {
public static class SimpleClass {
public static void doItStatic() {
}
public void doItNonStatic() {
}
}
interface MyOwnFunctionalInterface {
void methodA();
}
interface NotAFunctionalInterface {
void methodA();
void methodB();
}
interface AlsoNotAFunctionalInterface {
default void methodA() {
}
}
public static void main(String[] args) {
MyOwnFunctionalInterface compiles = SimpleClass::doItStatic;
MyOwnFunctionalInterface alsoCompiles = new SimpleClass()::doItNonStatic;
NotAFunctionalInterface doesNotCompile = SimpleClass::doItStatic;
AlsoNotAFunctionalInterface alsoDoesNotCompile = SimpleClass::doItStatic;
}
}
So I was just playing around with java 8 and thought of putting { } after creating an object and weirdly it didn't error out.
public class Guava{
public static void main(String [] args) {
Guava g = new Guava(){
int x=1;
public void func(){
System.out.println("LOL");
}
};
}
}
Was expecting the code to error out in line
Guava g = new Guava(){ ... };
So I want to know if there's a way to actually use the variable 'x' and method 'func' and if this is an actual concept under java that I don't know about? (closures maybe?)
Thanks
Guava g = new Guava(){ ... }; creates an anonymous inner-class.
It is an inner class without a name and for which only a single object is created.
In your example, the inner class inherits from Guava.
This question already has answers here:
Require a default constructor in java?
(3 answers)
Closed 8 years ago.
I've tried running the following code which gives me a constructor A in class A cannot be applied to given types error.
class A{
int a;
A(int b){
a = b;
}
}
public static void main (String[] args) throws java.lang.Exception
{
A a = new A();
System.out.println(a.a);
}
If I remove the c'tor from class A however the code runs as expected (and outputs 0). It seems that if another c'tor exists there is no default c'tor (and an argument less c'tor exists only if it is written). Am I correct?
More importantly, why is this?
If you don't create a constructor then there is a constructor by default as below
public YourClass(){
}
But if you create a constructor like below:
public YourClass(int x){
}
Then you won't have a constructor by default i.e.
public YourClass(){
//this won't exist
}
So you have to do
YourClass anObject = new YourClass(5);//you can do this.
And hence you cannot do something like
YourClass anObject = new YourClass();//you cannot do this
In order to do this you need to create a constructor by yourself as
public YourClass(){
//this time you must create this
}
For the question why?, I doubt there is any reason. This is the way OOP has moved.
Once you defined a non-empty constructor, the non-empty conscrutor isn't implicite and you have to explicite it.
public A() {
}
This question already has answers here:
Uninitialized variables and members in Java
(7 answers)
Closed 8 years ago.
I have a question that why this code is giving me an error while i am trying to call a static function defined within a class through a class reference and it makes possible to call a static function when i am creating an object of a reference.
public class Example
{
public static void main(String args[])
{
Example t;
t.method();//getting error
Example t1=new Example t1();
t1.method();//it runs successfully
}
public static void method()
{
System.out.println("NullPointerException");
}
}
You should not call a static method on an instance of the class. You should use name of the class itself:
Example.method()
Also when you declare a variable and left it without initialization, It will not be initialized (Local variables) and when you try to call a method on it, you will get error
t is not initialised when you call t.method();. You therefore get a NullPointer on the non-instanciated t object.
public class Example
{
public static void main(String args[])
{
Example t; // t points to nothing (not even null, actually, its as if it doesn't exist at all)
t.method();//getting error // how can you call a method of example with a reference to nothing.
Example t1=new Example t1(); // t1 points to an Example object.
t1.method();//it runs successfully // works fine , but is not suggested as the method is at class level, not at instance level. use Example.method()
}
public static void method()
{
System.out.println("NullPointerException");
}
}
that is possible, but if you want to call anything through a reference, you need to instantiate it first.
do remember also: Java has methods, not functions. So, change:
Example t;
in
Example t = new Example();
and try again
This question already has answers here:
What's wrong with overridable method calls in constructors?
(8 answers)
Closed 5 years ago.
Let's suppose I have an abstract Base class that implements Runnable interface.
public abstract class Base implements Runnable {
protected int param;
public Base(final int param) {
System.out.println("Base constructor");
this.param = param;
// I'm using this param here
new Thread(this).start();
System.out.println("Derivative thread created with param " + param);
}
#Override
abstract public void run();
}
And here is one of a few derivative classes.
public class Derivative extends Base {
public Derivative(final int param) {
super(param);
}
#Override
public void run() {
System.out.println("Derivative is running with param " + param);
}
public static void main(String[] args) {
Derivative thread = new Derivative(1);
}
}
The point is that I want my Base class do some general stuff instead of copying it every time.
Actually, it's running fine, the output is always the same:
Base constructor
Derivative thread created with param 1
Derivative is running with param 1
But is it safe IN JAVA to start a thread calling the abstract method in constructor? Because, in C++ and C# it is unsafe in most cases, so far as I know.
Thank you!
This code demonstrates why you should never call an abstract method, or any other overridable method, from a constructor:
abstract class Super {
Super() {
doSubStuff();
}
abstract void doSubStuff();
}
class Sub extends Super {
String s = "Hello world";
void doSubStuff() {
System.out.println(s);
}
}
public static void main(String[] args) {
new Sub();
}
When run, this prints null. This means the only "safe" methods to have in a constructor are private and/or final ones.
On the other hand, your code doesn't actually call an abstract method from a constructor. Instead, you pass an uninitialized object to another thread for processing, which is worse, since the thread you're starting may be given priority and execute before your Base finishes its initialization.
Not a good idea since when run() is invoked, the Derivative object may not have been initialized. If run() depends on any state in Derivative, it can fail.
In your simple case it works. But then there's no point for the subclass. You can simply
public Base(final int param, Runnable action) {
new Thread(action).start();
It's a very bad practice to call an abstract method from a constructor. Methods called from constructors should always be private or final, to prevent overriding.
See this link to a question here
Passing this out of the constructor is called "letting this escape from the constructor", and can lead to some particularly nasty and weird bugs, because the object may be in an inconsistent state.
This is especially the case when this is passed to another thread, as in this example. Due to the JVMs right to reorder statements within a thread, you can get undefined behaviour/state occurring.