I'm confused with method references. Consider the following script.
public class Main {
static interface I {
void m();
}
static class A implements I {
#Override
public void m() {
System.out.println("A");
}
}
static class B implements I {
#Override
public void m() {
System.out.println("B");
}
}
public static void main(String[] args) {
A a = new A(); B b = new B();
I i; Runnable r;
i = a;
r = i::m; // static reference? might infere class
r.run(); // prints "A"
run(i); // also prints "A"
i = b;
r.run(); // prints "A" instead of "B"!
run(i); // prints "B"
r = i::m;
r.run(); // now prints "B"
run(i); // also prints "B"
}
public static void run(I i) {
Runnable r = i::m; // dynamic reference, cannot infere class
r.run();
}
}
So it seems that:
The compiler cannot inline method references because they are polymorphic. They are not resolved at compilation time, but at runtime.
But i::m does not behave like i.m()...
So my questions are:
Are method references using reflection? And why they do only once?
If you think about how this code would be written without method references, but with classes and objects, it all makes sense:
r = i::m;
is basically equivalent to
private class IRunnable implements Runnable {
private I i;
public IRunnable(I i) {
this.i = i;
}
#Override
public void run() {
i.m();
}
}
Runnable r = new IRunnable(i);
So, if you assign another value to i after the IRunnable has been constructed, the IRunnable continues referencing the previous value, and calling its run() method again will still call the previous i's method.
Related
I have created 3 classes, one superclass "a" and under a two subclasses "b" and "c". I am creating an instance of c, give it an integer "n" and then use subclass b to do some calculation. The problem I am having is that when I create an instance c to call b, the data technically belong to the superclass a/c right? so when i create an instance of b with
b b_instance = new b();
inside the instance of c,
the b calc() function I call would return 0. I guess it's because b has it's own eco-sphere of data?
How do I do this?
2)
Also, how do i call the superclass function of the same name?
Thanks!
public class prog
{
public static void main(String args[])
{
c c1 = new c();
c1.run();
}
}
class a
{
private int number;
void set_number(int n)
{
number = n;
}
int get_number()
{
return number;
}
int calc()
{
return number*2;
}
}
class b extends a
{
int calc()
{
// calling the superclass function calc, then subtract
return super.calc() - get_number();
}
}
class c extends a
{
void run()
{
set_number(1);
b b1 = new b();
System.out.println(b1.calc());
}
}
infinite loop problem
public class prog
{
public static void main(String args[])
{
c c1 = new c();
c1.run();
}
}
class a
{
void calc_a()
{
System.out.println("") ;
}
void calc_b()
{
calc_a(); // meaning the calc_a() in the superclass
}
}
class b extends a
{
void calc_a()
{
super.calc_b();
}
}
class c extends a
{
void run()
{
b b1 = new b();
b1.calc_b();
}
}
b b_instance = new b();
inside the instance of c, the b calc() function I call would return 0.
I guess it's because b has it's own eco-sphere of data?
How do I do this?
A "couple" of possible ways. I'd consider extending c from b, this way c gets all the functionality of a and b, something like...
class c extends b {
void run() {
set_number(1);
System.out.println(calc());
}
}
IF, however, this is not feasible (for some reason or other), then you need to pass the value that c has to b, something like...
class c extends a {
void run() {
set_number(1);
b b1 = new b();
b1.set_number(get_number());
System.out.println(b1.calc());
}
}
Now, having said that, this "smells" to me. What's the point of extending from a just so c can perform b? It would set off alarm bells to me.
The problem is, if your call c#calc, it's just going to a's calc method ... which, based on run, doesn't seem to be what you want to achieve, so it's all just a big mess
2)
Also, how do i call the superclass function of the same name?
Because calling calc directly would cause a StackOverflowError because you're constantly calling yourself.
In this case, you're taking the operation that a is doing and making a modification to it. This is a common practice in OO languages.
Side notes...
Java (and the Java community) already have a well defined set of coding practices. You should take the time to learn them, it will make your code easier to read and make it easier for you to read other peoples codes.
Start with Code Conventions for the Java TM Programming Language
Class names should start with a capital letter and methods are in camelCase, for example...
class A {
private int number;
void setNumber(int n) {
number = n;
}
int getNumber() {
return number;
}
int calc() {
return number * 2;
}
}
Updated...
class a {
void calc_a() {
System.out.println("");
}
void calc_b() {
calc_a(); // meaning the calc_a() in the superclass
}
}
class b extends a {
void calc_a() {
super.calc_b();
}
}
class c extends a {
void run() {
b b1 = new b();
b1.calc_b();
}
}
The question you need to ask yourself is, why does b need to override calc_a? Why not override calc_b? It would solve the issue
how do i override it?
class b extends a {
//void calc_a() {
// super.calc_b();
//}
#Override
void calc_b() {
super.calc_b();
}
}
This question already has answers here:
Is there a way to override class variables in Java?
(17 answers)
Overriding member variables in Java ( Variable Hiding)
(13 answers)
Closed 5 years ago.
I am not able to understand the following output.
I don't know why the output is 10, I think the line A a = new B() creates a new instance of class B, I think the result should be 20
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
}
}
Why this works like this .. please explain.
First, see Hiding Fields (emphasis added)
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different
In other words, this isn't "inheritance" since you're actually hiding A's i behind B's i, and you are using a reference object of A, so you are getting its fields. If you did B b = new B(), you would see 20, as expected.
If you expect true overrides, try using methods.
class A {
public int get() {
return 10;
}
}
class B extends A {
#Override
public int get() {
return 20;
}
}
See
A a = new B();
System.out.print(a.get()); // 20
If you really want to see both at once, see this example.
class A {
int i = 10;
}
class B extends A {
int i = 20;
#Override
public String toString() {
return String.format("super: %d; this: %d", super.i, this.i);
}
}
And
A a = new B();
System.out.print(a); // super: 10; this: 20
In java you cannot override an instance variable. The output you are getting is expected. In Java you can only override instance methods and not instance variables.
If you want 20 as an output you may use getter methods over those instance variables.
class A {
int i = 10;
int getI() {
return i;
}
}
class B extends A {
int i = 20;
int getI() {
return i;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getI());
}
}
Polymorphism is not applicable for fields in Java.Evaluating Variables decision is taken at compile time so always base class variables are accessed.
Because you define 2 variables: one in the subclass B, and one with the same name in superclass A.
A a = new B();
a.i; // refers to A.i
If you cast the A to a B, it will access B.i:
System.out.println(((B)a).i);
I think you need to use 1 variable:
class A {
int i;
public A() {
i = 10;
}
}
class B extends A {
public B() {
i = 20;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i); // will print 20
}
Member variable i is already defined in class A.
In order to achieve what you are looking for, change the class B as shown below:
class B extends A {
public B() {
i = 20;
}
}
I'm trying to implement stopwatch class that will wrap all the required methods that i'm trying to measure
The main purpose is to create an framwork that when ever you want to measure the execution time of a method you will change the exiting code from:
<Classname> x = A();
or
A();
To:
<Classname> x = PSW.startWatch(MethodToWatch.B).invoke("123123123", A());
or
PSW.startWatch(MethodToWatch.B).invoke("123123123", A());
This is the code:
public class PerformanceStopWatch {
private long start;
private long end;
private String uniqueID;
private MethodToWatch methodName;
public enum MethodToWatch {
A,
B
}
public PerformanceStopWatch startWatch(MethodToWatch methodName) {
this.methodName = methodName;
start();
return this;
}
public void invoke(String uniqeID) {
this.uniqueID = uniqeID;
stop();
}
public void invoke(UUID machineId, void a) {
invoke(machineId);
}
private void start() {
start = System.nanoTime();
}
private void stop() {
end = System.nanoTime();
System.out.println("[PerformanceStopWatch|"+methodName.name()+"] - Unique ID: "+ uniqueID + " Took: <"+(end-start)+"> Nanosec");
}
}
public void a() {
PerformanceStopWatch PSW = new PerformanceStopWatch();
..
..
..
PSW.startWatch(MethodToWatch.B).invoke("123123123", b());
}
public void b() {
...
...
..
}
The problem is that the compiler dose not allow me to use
public void invoke(UUID machineId, void a) {
}
void is illegle type.
any idea?
You can try Void insteed of void (Capital V) as the second one is not a type in strict sense. Void on the other hand is.
But in general if you want to invoke with "void" you simply ommit arguments (talking about reflection here)
EDIT: to your comment
public void invoke(UUID machineId, Void a) { //note the capital V
invoke(machineId);
}
Will compile just fine, but I dont see any usable usecase for such method signature.
It looks like you want to pass a method to the invoke() method. Since the method you are passing returns nothing and has no arguments, you should use Runnable interface :
public void invoke(UUID machineId, Runnable a) {
invoke(machineId);
a.run();
}
and
PSW.startWatch(MethodToWatch.B).invoke("123123123", () -> {b();});
or (if you are not using Java 8) :
PSW.startWatch(MethodToWatch.B).invoke("123123123",
new Runnable() {
public void run() {
b();
}
});
What exactly do you want to do? There are no objects or values of type void, so if it would have been allowed, you would not be able to call the method.
Maybe what you want is to be able to pass an object of any type. In this case you can use Object:
public void invoke(UUID machineId, Object a) {
invoke(machineId);
}
Since every class is a subclass of Object, now you can pass any object as the second argument to this method, including arrays. You can also pass primitive types (they will be wrapped to their corresponding wrapper class).
The relevant summary of my code is this:
public class A {
String aString;
public static void main(String[] args) {
B b = new B();
new Thread(b).start();
}
public static class B implements Runnable {
public void run() {
aString = "foo";
}
}
}
I have had a few months of Java coding experience but thread and dynamic vs. static is still rather new to me. In order for the thread to execute properly, class B must be static, or else only the thread executes, not both. My goal is to obviously have the thread execute in the background so that other code that I may have in class A can execute simultaneously. Problem is, if class B is static, I can't manipulate the string aString, as I get the exception non-static variable aString cannot be referenced from a static context.
I've looked up information on this but I have not found anything that relates to fixing this issue in threads. My question is, how can I manipulate aString within class B and still get the thread to work properly (both classes running, not just class B)?
To make your example work, you'll need something like this:
public class A {
volatile String aString;
public static void main(String[] args) throws InterruptedException {
A a = new A();
Thread t = new Thread(a.new B());
t.start();
t.join(); // wait for t to finish
System.out.println(a.aString); // prints "foo"
}
class B implements Runnable {
public void run() {
aString = "foo";
}
}
}
Resolving the static issue is the easy part - see code for how.
I hope the rest of the code helps illustrate some of the issues you need to cater for when using threads.
B is static, so only only exists at the class level, and can therefore not see instance variables of its parent class
public class A {
String aString; // <== instance variable
public static void main(String[] args) {
B b = new B();
new Thread(b).start();
}
public static class B implements Runnable { // <== static class
public void run() {
aString = "foo";
}
}
}
Possible fix. Make aString static too
public class A {
static String aString;
Possible fix. Make B non-static. This is where it gets a bit weird. B now only exists at the instance level of A, so you need to create an A instance first.
public class A {
String aString;
public static void main(String[] args) {
B b = new A().new B(); // <== need to create an A before a B
new Thread(b).start();
}
public class B implements Runnable {
public void run() {
aString = "foo";
}
}
}
You are asking an object instance of class B (which you create using new B() )to access a member variable of an object instance that you haven't created. In your code, there is no object of class B created.
I think that you may be thinking that running the main() method in class A is somehow instantiating an instance of class A - this is not the case.
The following will work because you are creating an instance of A and making that available to your instance of B.
public class A {
String aString;
public static void main(String[] args) {
A a = new A();
B b = new B(a);
new Thread(b).start();
}
public static class B implements Runnable {
private final A a;
public B(A a){
this.a = a;
}
public void run() {
a.aString = "foo";
}
}
}
I want advice on what should I do:
I have a class A and B such that
public class A {
int result;
int a;
public A(){
result =0;
a = 5;
B myB= new B();
System.out.println(result);
}
public void main(){
A myA= new A();
}
}
public class B extends Thread {
public B(){
start();
}
public void run() {
addition1();
}
public void addition1() {
////////HERE trying to do///////
result = a+5;
}
}
Unfortunally, I need to use, peferable two classes and must two threads and the addition will be perform in the second thread and update the first thread.
This is just an example I came that shows what my issues are. my real code was far too long to post in here.
Thanks
I assume that when you say that you want to update from one thread to another you should have had Class A also as an extension of Thread or a Runnable object. However Class A in your example is not a Thread extension and can be updated by an operation in B (which is another thread) in a usual way like you can update a shared variable in multi threaded scenario. Just expose a setter method for the result variable in Class A and update it from the B class method (addition1) which is running in new thread. Therefore you would have updated a shared instance (of class A) being operated upon by main thread (the first thread) from another thread (spawned during construction of Class B) method (addition1)
You can try with Callback Mechanism to get the result back one it's computed.
For more info read inline comments.
Sample code:
interface Callback {
public void execute(int result);
}
// make it abstract and don't provide implementation of execute method here
abstract class B extends Thread implements Callback {
private A a;
// pass the reference of Class A to access it
public B(A a) {
this.a = a;
start();
}
public void run() {
addition1();
}
public void addition1() {
int result = a.a + 5;
//result is computed now call pass the value to the waiter and that's A
execute(result);
}
}
class A {
int result;
int a;
public A() {
result = 0;
a = 5;
B myB = new B(this) {// pass the reference of Class A
#Override
public void execute(int result) {
// This is the computed result that is returned from Class B
System.out.println(result);
}
};
}
}