what is the way in ASM visitors to figure out the class type of the class containing a static method.
My code looks like
public static class A {
public void a() {
B.b();
}
}
public static class B {
public static void b() {
}
}
So I want when visiting class A to be noticed that class B is being used
Related
This question already has an answer here:
Why can I override a static interface method?
(1 answer)
Closed 1 year ago.
Consider the following snippet:
interface Super{
public static void doIt(){}
}
class Sub implements Super{
public void doIt(){}
}
Here I have declared a static member method and it is being redeclared as the instance method in the child class.
This is allowed by the compiler - but when I do the same with the superclass and subclass types - this gives compilation error:
class Super{
public static void doIt(){}
}
class Sub extends Super{
public void doIt(){}
}
What is the rationale behind the same? - ideally the way to access the subclass is essentially the same - then why this restriction?
The reason for this is that Java allows invoking static methods in a non-static manner. Consider this example:
public class MyClass {
public static void sayHello() {
}
public void test() {
this.sayHello();
}
}
This will produce a compiler warning (The static method sayHello() from the type MyClass should be accessed in a static way), but it will compile and invoke the static method correctly at runtime.
That's why the following code will not compile because of an ambiguity (Duplicate method test() in type MyClass):
public class MyClass {
public static void test() {
}
public void test() {
}
}
The reason for the compile error is, that if you write the following, the compiler cannot know which method to invoke, because it allows to call static methods in a non-static manner:
public class MyClass {
public static void test() {
}
public void test() {
}
public void execute() {
this.test();
}
}
For the same reason it is not possible to have the static test() method in the parent class - the same rules apply. It is possible in Java to call static methods of super classes with or without qualification:
public class Super {
public static void test() {
}
}
public class Sub extends Super {
public void execute() {
this.test();
}
}
OR
public class Sub {
public void execute() {
test();
}
}
where the invocation of this.test() will produce a warning, but will work at runtime.
For static methods in interfaces, the above example will not work, because the compiler forces you to call the static method of the interface in a qualified manner (edit: because they are not being inherited). The following will not work (The method interfaceStatic() is undefined for the type Sub):
public interface Interface {
public static void interfaceStatic() {
}
}
public class Sub implements Interface {
public void test() {
interfaceStatic();
}
}
In order to call interfaceStatic() the invocation has to be qualified like this:
public class Sub implements Interface {
public void test() {
Interface.interfaceStatic();
}
}
That's the difference between defining the static method in an interface and defining it in the super class: The way of invocation. If you implement multiple interfaces which all have a static method with the same signature, the compiler cannot know which one to call.
This is the reason why it is allowed to define a static method with the same signature in an implemented interface, but not in the parent classes.
How to use a non-abstract method from an abstract class in another class without extending?
Abstract Class:
package com.test;
public abstract class MyAbstract {
public abstract void abstractMethod();
public void callNonAbstractMethod() {
System.out.println("Hello");
}
}
The anonymous class:
package com.test;
public class Example {
public static void main(String[] args) {
new Example().something();
}
void something() {
MyAbstract a = new MyAbstract() {
#Override
public void abstractMethod() {
//TODO implement
}
};
a.callNonAbstractMethod();
}
}
Internal class generated by the compiler would be for above example.
static class Example extends MyAbstract
{
Example(){}
void abstractMethod()
{
System.out.println("hiee");
}
}
Abstract Class:
package com.test;
public abstract class MyAbstract {
public abstract void abstractMethod();
public void callNonAbstractMethod() {
System.out.println("Hello");
}
}
You can't.
To call any non-static method of some class A, you need an instance of A or of a subclass of A, as such a method typically operates on data within such an instance. That's at the very core of what "object-oriented" is all about.
In your case, A is abstract and can't have direct instances. So the only way to call your method is to have some instance of some class B that extends A. You can either find an existing subclass that you can use, or create your own subclass.
I think you can use an anonymous class. Although it is a kind of extension, you are not explicitly using the keyword extends. In fact, you cannot use any class in java without implicitly extending because every class extends Object.
package com.test;
public class Example {
public static void main(String[] args) {
new Example().something();
}
void something() {
MyAbstract a = new MyAbstract() {
#Override
public void abstractMethod() {
//TODO implement
}
};
a.callNonAbstractMethod();
}
}
and here's your abstract class:
package com.test;
public abstract class MyAbstract {
public abstract void abstractMethod();
public void callNonAbstractMethod() {
System.out.println("Hello");
}
}
results in:
Hello
I have a class in jar of which I want to invoke a method. But that method has parameter of abstract class and that abstract class is inner method of class in jar. AbstractClassA is a HIDDEN class. Here is code:
public class A{
private invokeThisMethod(AbstractClassA object){
}
public abstract class AbstractClassA {
public void update(int remaining){}
}
}
public class myClass{
//using Reflection get object of class A
objectOfClassAusingReflection.inovke("invokeThisMethod", params)
}
Problem here is how do I create concrete implementation of AbstractClassA to pass in invoke method and get update method callbacks ?
Something like this should work:
AbstractClassA a = new AbstractClassA() {
public void update(int remaining) {... do something...}
};
objectOfClassAusingReflection.inovke("invokeThisMethod", a);
You cannot create an instance of abstract class or any interface at runtime.
Instead create an anonymous class for this.
public abstract class A {
public void fun(){....}
public abstract void absFun();
}
public class MyClass {
objectOfClassA = new A(){
public void absFun(){...}
}
}
Or you can first create implementation for that abstract classes for which you will have to create another class extending A
class AWrapper extends A {
public class ImplementationClassA extends AbstractClassA {
// override abstract functions...
}
}
Now you can use this Awrapper class
AWrapper wrapperObj = new AWrapper();
A obj = wrapperObj; // just to make it clear that A can hold wrapperObj as it is implementation of it.
A.AbstractClassA absObj = wrapperObj.new ImplementationClassA();
...
objectOfClassAusingReflection.inovke("invokeThisMethod", params)
Below code should work--
Here, i used anonymus classes for both outer and inner class and then with the help of getdeclatedMethod called your update method.
"TestAbs" is your jar class--
public abstract class TestAbs {
private void invokeThisMethod(AbstractClassA object) {
}
public abstract class AbstractClassA {
public void update(int remaining) {
}
}
}
Then calling your jar class from "TestAbs1" like below--
public class TestAbs1 {
public static void main(String[] args) {
TestAbs.AbstractClassA abs = new TestAbs() {
AbstractClassA a = new AbstractClassA() {
public void update(int remaining) {
System.out.println("Inside update method : " + remaining);
}
};
}.a;
try {
int i = 1;
Class<?> class1 = Class.forName("app.test.mytest.TestAbs$AbstractClassA"); -- (*Getting instance of inner class*)
System.out.println(class1.getDeclaredMethod("update", int.class));
class1.getDeclaredMethod("update", int.class).invoke(abs, i);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The output i got is --
public void app.test.mytest.TestAbs$AbstractClassA.update(int)
Inside update method : 1
Answer to your Comment:-
What I understood from your comment is that, you wanted to call method from abstractClass which is hidden in outerclass.
As per my understanding, there is one way like below--
public abstract class TestAbs {
private void invokeThisMethod(AbstractClassA object) {
}
private abstract class AbstractClassA { --- your hidden class
public void update(int remaining) {
}
}
public class ImplementedClass extends AbstractClassA{ -- use implemented class here
....
...
}
}
And after that, use your ImplementedClass the same way mentioned above.
You can find reference example for private inner class here from java docs.
Note: In your question context, since your inner class and outer class is in jar, so I think it is difficult for you add implementation class in your jar.
In case, you find any alternatives, please let all knows about this;
thanks.
How to access the public function of private static inner class in some other class Suppose there is a class structure like below :-
public class Outer{
private static Inner {
public void func() {
}
}
}
And there is another class :-
class UseFunc {
// I have to use the func() here
}
If I use like this it will give error : - create object of Inner like Outer.Inner oi = new Outer.Inner();
access oi.func() //as Inner is private class
Okay, this is a very bad (I mean, really terrible) implementation but it works:
public class Outer
{
private static class Inner
{
public void func()
{
}
}
public void encapsulatedFunc()
{
new Inner().func();
}
}
class UseFunc
{
public static void main(String[] args)
{
new Outer().encapsulatedFunc();
}
}
I can only imagine that code being used for educational purpose as a "What not to do" example.
I have an abstract class which is inherited by classes that run on different threads. do the variables in this abstract class act as shared memory?
public abstract class A
{
public abstract void foo();
public boolean bar(){
{
List<String> x=new ArrayList();
x.add("a");
//some code
}
}
public class B extends A
{
#Override
public void foo()
{
//some code
}
}
public class C extends A
{
#Override
public void foo()
{
//some code
}
#Override
public boolean bar()
{
List<String> x=new ArrayList();
x.add("a");
//some code
}
}
public class D extends A
{
#Override
public void foo()
{
//some code
}
}
classes B, C and D run in different threads. however x is behaving like a shared memory for A and B and D. is it the expected behaviour? if yes how can i make it thread specific without overriding?
the x variable is not being shared. It's replicated on any thread that invokes the bar() method. If its content is always the same, you should declare it as static final member variable. That is:
public abstract class A
{
static final List<String> x=new ArrayList();
Probably it'd also be a good idea to initialize it through a static initializer: Static initializer in Java