In java, how can you get the object calling a method, within the method it is calling, if the method is in another class? I have looked all over the internet and no solution. Could someone please help?
The only way I can think of is to pass this to the method,
static void someMethod(Object o) {
System.out.println(o);
}
void testIt() {
someMethod(this); // <-- pass the current instance to the method.
}
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()
The last element of this array will be the recent object you have used. But it should better to use an extra argument as above answer said and pass this object.
If you know in advance that you need to receive an instance of the first class then you can prepare the second class to receive it as follows.
public class class1 {
public static void main(String[] args)
{
new class1();
}
public class1()
{
send();
}
private void send()
{
new class2().receiveClass(this);// creates an instance of class 2 and sends a reference of class1 (this)
}
public void print()
{
System.out.println("class1.print()");
}
}
To receive in the second class.
public class class2 {
private class1 c1;
public void receiveClass(class1 c)
{
c1=c;
c1.print(); //accessing the print method of class1, the same instance that references this object.
}
}
This will also work if the solutions given above do not work for you.
Related
Here's an example:
class A
{
List l = new List ();
list.insert("x");
}
class List
{
...
public void insert ()
{
/*insertion occurs*/
}
...
}
Is it possible at all to keep the insert() method public, but limit access only to class A so that no other class can access it, only when called from A?
I would pass the object that is calling the method as an argument, i.e.
list.insert("x", this);
And then check if the passed Object is an Instance of Class A
public void insert (String x, Object o)
{
if(o instanceof ClassA){
/*insertion occurs*/
}
}
If the method is public, everyone can access it. The trick to access control like yours is to expose a set of public operations through an interface, add auxiliary operations to a private class implementing the interface, and make your users program to the interface, not to a class.
Here is an example:
public interface MyList {
Object elementAt(int i);
}
public class A {
private static class MyListImpl implements MyList {
public Object elementAt(int i) {
...
}
public void insert(Object element) {
...
}
}
private final MyListImpl list = new MyListImpl();
public MyList getList() { return list; }
public void insert(Object o) { list.insert(o); }
}
Usage scenario:
A a = new A();
a.insert(123);
a.insert("quick brown fox");
MyList lst = a.getList();
System.out.println(lst.elementAt(0));
System.out.println(lst.elementAt(1));
Yes, you can pass calling object as an argument and put a check in insert() method before actual code.
public void insert(Object obj){
if(obj instanceof A){
//your code block
}
}
Please note that this will allow all the classes that extends A as well to call insert. If you want to restrict only for class A, add additional check.
public void insert(Object obj){
if((obj instanceof A) && obj.getClass().getSimpleName().equals("A")){
//your code block
}
}
we can also achieve second case with only condition "obj.getClass().getSimpleName().equals("A")" as well.
The best you can do using access modifiers is to make the method package private (remove the public keyword) and keep only those two classes in the same package.
If all the "inner classes" stuff in the previous answers confuses you, there is another way that may be more intuitive (assuming you've learned about the extends keyword and inheritance). You can simply make the insert() method protected instead of public and make class A extend List. For example:
public class List {
...
protected void insert() {
//insertion occurs
}
...
}
public class A extends List {
...
}
As long as no other classes extend List, only objects of types A and List will ever be able to use the insert() method.
package problems;
public class Problem1 {
public static void main(String[] args) {
B b = new B();
b.methodInB();
C c = new C();
c.methodNotInB();
}
}
class A {
public void onlyB() {
StackTraceElement[] stackTraceElements = Thread.currentThread()
.getStackTrace();
if (!problems.B.class.getCanonicalName().equals(
stackTraceElements[stackTraceElements.length - 2]
.getClassName())) {
System.err.println("You are not authorized to call me!!");
return;
}
System.out.println("You are authorized to call me!!");
}
}
class B {
public void methodInB() {
A a = new A();
a.onlyB();
}
}
class C {
public void methodNotInB() {
A a = new A();
a.onlyB();
}
}
Put it as inner class in A or you can do another thing ...
Let insert takes one parameter with type of Object and in the beginning of it check if the parameter's type is A .... and when you call it send the calling object...
maby its not a good idea but it will do what you want
Put it into the permitted class and make it private.
Is there any Java syntax to access new methods defined within anonymous inner classes from outer class? I know there can be various workarounds, but I wonder if a special syntax exist?
For example
class Outer {
ActionListener listener = new ActionListener() {
#Override
void actionPerformed(ActionEvent e) {
// do something
}
// method is public so can be accessible
public void MyGloriousMethod() {
// viva!
}
};
public void Caller() {
listener.MyGloriousMethod(); // does not work!
}
}
MY OWN SOLUTION
I just moved all methods and members up to outer class.
Once the anonymous class instance has been implicitly cast into the named type it can't be cast back because there is no name for the anonymous type. You can access the additional members of the anonymous inner class through this within the class, in the expression immediate after the expression and the type can be inferred and returned through a method call.
Object obj = new Object() {
void fn() {
System.err.println("fn");
}
#Override public String toString() {
fn();
return "";
}
};
obj.toString();
new Object() {
void fn() {
System.err.println("fn");
}
}.fn();
identity(new Object() {
void fn() {
System.err.println("fn");
}
}).fn();
...
private static <T> T identity(T value) {
return value;
}
A student in my class asked our professor if this could be done the other day. Here is what I wrote as a cool proof of concept that it CAN be done, although not worth it, it is actually possible and here is how:
public static void main(String[] args){
//anonymous inner class with method defined inside which
//does not override anything
Object o = new Object()
{
public int test = 5;
public void sayHello()
{
System.out.println("Hello World");
}
};
//o.sayHello();//Does not work
try
{
Method m = o.getClass().getMethod("sayHello");
Field f = o.getClass().getField("test");
System.out.println(f.getInt(o));
m.invoke(o);
} catch (Exception e)
{
e.printStackTrace();
}
}
By making use of Java's Method class we can invoke a method by passing in the string value and parameters of the method. Same thing can be done with fields.
Just thought it would be cool to share this!
Your caller knows listener as an ActionListener and therefore it doesn't know anything about that new method. I think the only way to do this (other than doing reflection gymnastics, which really would defeat the purpose of using an anonymous class, i.e. shortcut/simplicity) is to simply subclass ActionListener and not use an anonymous class.
Funny enough, this is now allowed with var construct (Java 10 or newer). Example:
var calculator = new Object() {
BigDecimal intermediateSum = BigDecimal.ZERO;
void calculate(Item item) {
intermediateSum = Numbers.add(intermediateSum, item.value);
item.sum= intermediateSum;
}
};
items.forEach(calculator::calculate);
Here with method reference, but works with dot method call as well, of course. It works with fields as well. Enjoy new Java. :-)
I found more tricks with var and anonymous classes here: https://blog.codefx.org/java/tricks-var-anonymous-classes/
No, it's imposible. You would need to cast the ActionListener to its real subclass name, but since it's anonymous, it doesn't have a name.
The right way to do it is using reflection:
import java.lang.reflect.InvocationTargetException;
public class MethodByReflectionTest {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Object obj = new Object(){
public void print(){
System.out.println("Print executed.");
}
};
obj.getClass().getMethod("print", null).invoke(obj, null);
}
}
You can check here: How do I invoke a Java method when given the method name as a string?
Yes you can access the method see the example below if any doubt please comment
package com;
interface A
{
public void display();
}
public class Outer {
public static void main(String []args)
{
A a=new A() {
#Override
public void display() {
System.out.println("Hello");
}
};
a.display();
}
}
lets say I have below
class abc{
void doSomething(String abc){
//does Something
}
}
I need to be able to create a function that I can pass the full call
as parameter.
functionCall(doSomething(abc)){}
please advice if this is possible. similar to what happens in an if
statement.
Create a function that takes a Consumer functional interface as argument
public static void functionCall(Consumer<String> consumer, String value) {
consumer.accept(value);
}
Then use it like below, this solution is for Java 8. For newer versions you can do this in a cleaner way. See answer from #akuzminykh
Abc abc = new Abc();
functionalCall(s -> abc.doSomething(s), "Hi");
You can pass a function with one parameter and no return type as Consumer<T>.
static void functionCall(Consumer<String> function, String argument) {
function.accept(argument); // Call the method with the argument.
}
...
Abc object = new Abc();
Consumer<String> function = object::doSomething; // Get function variable.
functionCall(function, "foobar");
As your method is an instance method, you need to get the method reference through an instance of the class. This is what I have object for. This syntax works on Java 11.0.6.
You can put the method doSomething in an abstract class (Abc) and then create a anonymous class an call the method that you want ie:
public class TemplateExample {
public static void main(String args[]) {
TemplateExample instance = new TemplateExample();
PrintSomething pa = instance.new PrintSomething() {
#Override
void print() {
System.out.println("PrintSomething pa");
}
};
PrintSomething pb = instance.new PrintSomething() {
#Override
void print() {
System.out.println("PrintSomething pb");
}
};
pa.print();
pb.print();
}
abstract class PrintSomething {
abstract void print();
}
}
Is there any Java syntax to access new methods defined within anonymous inner classes from outer class? I know there can be various workarounds, but I wonder if a special syntax exist?
For example
class Outer {
ActionListener listener = new ActionListener() {
#Override
void actionPerformed(ActionEvent e) {
// do something
}
// method is public so can be accessible
public void MyGloriousMethod() {
// viva!
}
};
public void Caller() {
listener.MyGloriousMethod(); // does not work!
}
}
MY OWN SOLUTION
I just moved all methods and members up to outer class.
Once the anonymous class instance has been implicitly cast into the named type it can't be cast back because there is no name for the anonymous type. You can access the additional members of the anonymous inner class through this within the class, in the expression immediate after the expression and the type can be inferred and returned through a method call.
Object obj = new Object() {
void fn() {
System.err.println("fn");
}
#Override public String toString() {
fn();
return "";
}
};
obj.toString();
new Object() {
void fn() {
System.err.println("fn");
}
}.fn();
identity(new Object() {
void fn() {
System.err.println("fn");
}
}).fn();
...
private static <T> T identity(T value) {
return value;
}
A student in my class asked our professor if this could be done the other day. Here is what I wrote as a cool proof of concept that it CAN be done, although not worth it, it is actually possible and here is how:
public static void main(String[] args){
//anonymous inner class with method defined inside which
//does not override anything
Object o = new Object()
{
public int test = 5;
public void sayHello()
{
System.out.println("Hello World");
}
};
//o.sayHello();//Does not work
try
{
Method m = o.getClass().getMethod("sayHello");
Field f = o.getClass().getField("test");
System.out.println(f.getInt(o));
m.invoke(o);
} catch (Exception e)
{
e.printStackTrace();
}
}
By making use of Java's Method class we can invoke a method by passing in the string value and parameters of the method. Same thing can be done with fields.
Just thought it would be cool to share this!
Your caller knows listener as an ActionListener and therefore it doesn't know anything about that new method. I think the only way to do this (other than doing reflection gymnastics, which really would defeat the purpose of using an anonymous class, i.e. shortcut/simplicity) is to simply subclass ActionListener and not use an anonymous class.
Funny enough, this is now allowed with var construct (Java 10 or newer). Example:
var calculator = new Object() {
BigDecimal intermediateSum = BigDecimal.ZERO;
void calculate(Item item) {
intermediateSum = Numbers.add(intermediateSum, item.value);
item.sum= intermediateSum;
}
};
items.forEach(calculator::calculate);
Here with method reference, but works with dot method call as well, of course. It works with fields as well. Enjoy new Java. :-)
I found more tricks with var and anonymous classes here: https://blog.codefx.org/java/tricks-var-anonymous-classes/
No, it's imposible. You would need to cast the ActionListener to its real subclass name, but since it's anonymous, it doesn't have a name.
The right way to do it is using reflection:
import java.lang.reflect.InvocationTargetException;
public class MethodByReflectionTest {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Object obj = new Object(){
public void print(){
System.out.println("Print executed.");
}
};
obj.getClass().getMethod("print", null).invoke(obj, null);
}
}
You can check here: How do I invoke a Java method when given the method name as a string?
Yes you can access the method see the example below if any doubt please comment
package com;
interface A
{
public void display();
}
public class Outer {
public static void main(String []args)
{
A a=new A() {
#Override
public void display() {
System.out.println("Hello");
}
};
a.display();
}
}
Here's an example:
class A
{
List l = new List ();
list.insert("x");
}
class List
{
...
public void insert ()
{
/*insertion occurs*/
}
...
}
Is it possible at all to keep the insert() method public, but limit access only to class A so that no other class can access it, only when called from A?
I would pass the object that is calling the method as an argument, i.e.
list.insert("x", this);
And then check if the passed Object is an Instance of Class A
public void insert (String x, Object o)
{
if(o instanceof ClassA){
/*insertion occurs*/
}
}
If the method is public, everyone can access it. The trick to access control like yours is to expose a set of public operations through an interface, add auxiliary operations to a private class implementing the interface, and make your users program to the interface, not to a class.
Here is an example:
public interface MyList {
Object elementAt(int i);
}
public class A {
private static class MyListImpl implements MyList {
public Object elementAt(int i) {
...
}
public void insert(Object element) {
...
}
}
private final MyListImpl list = new MyListImpl();
public MyList getList() { return list; }
public void insert(Object o) { list.insert(o); }
}
Usage scenario:
A a = new A();
a.insert(123);
a.insert("quick brown fox");
MyList lst = a.getList();
System.out.println(lst.elementAt(0));
System.out.println(lst.elementAt(1));
Yes, you can pass calling object as an argument and put a check in insert() method before actual code.
public void insert(Object obj){
if(obj instanceof A){
//your code block
}
}
Please note that this will allow all the classes that extends A as well to call insert. If you want to restrict only for class A, add additional check.
public void insert(Object obj){
if((obj instanceof A) && obj.getClass().getSimpleName().equals("A")){
//your code block
}
}
we can also achieve second case with only condition "obj.getClass().getSimpleName().equals("A")" as well.
The best you can do using access modifiers is to make the method package private (remove the public keyword) and keep only those two classes in the same package.
If all the "inner classes" stuff in the previous answers confuses you, there is another way that may be more intuitive (assuming you've learned about the extends keyword and inheritance). You can simply make the insert() method protected instead of public and make class A extend List. For example:
public class List {
...
protected void insert() {
//insertion occurs
}
...
}
public class A extends List {
...
}
As long as no other classes extend List, only objects of types A and List will ever be able to use the insert() method.
package problems;
public class Problem1 {
public static void main(String[] args) {
B b = new B();
b.methodInB();
C c = new C();
c.methodNotInB();
}
}
class A {
public void onlyB() {
StackTraceElement[] stackTraceElements = Thread.currentThread()
.getStackTrace();
if (!problems.B.class.getCanonicalName().equals(
stackTraceElements[stackTraceElements.length - 2]
.getClassName())) {
System.err.println("You are not authorized to call me!!");
return;
}
System.out.println("You are authorized to call me!!");
}
}
class B {
public void methodInB() {
A a = new A();
a.onlyB();
}
}
class C {
public void methodNotInB() {
A a = new A();
a.onlyB();
}
}
Put it as inner class in A or you can do another thing ...
Let insert takes one parameter with type of Object and in the beginning of it check if the parameter's type is A .... and when you call it send the calling object...
maby its not a good idea but it will do what you want
Put it into the permitted class and make it private.