Can you invoke nonstatic method within a static method? - java

Book answer: you cannot invoke a nonstatic method within a static method(unless you create an object to serve as the calling object of the non static method). I don't get the part in bracket, I tried creating object in static method and eclipse said "unreachable code". Can someone explain why and give an example too. Thanks
(language is java)
public class RoundStuff {
public static final double PI = 3.141459;
public static double area(double radius){//Area of circle
return(PI*radius*radius);
}
public static double volume(double radius){//Volume of sphere
return((4.0/3.0)*PI*radius*radius*radius);
}
public void print(){
System.out.print("I am not parasyte");
}
}
import java.util.Scanner;
public class RoundStuffDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter radius");
double radius = keyboard.nextDouble();
RoundStuff round = new RoundStuff();
System.out.println("A circle of radius " + radius + " inches");
System.out.println("has an area of " + round.area(5.5) + " square inches.");
System.out.println("A sphere of radius " + radius + " inches");
System.out.println("has a volume of " + RoundStuff.volume(radius) + " cubic inches.");
}
}

Java lets non-static methods call other non-static methods without specifying an object reference explicitly. It is understood that the invocation is performed on the same instance on which the current non-static method has been invoked, i.e. the instance that you can access by referencing this.
Static methods, on the other hand, must provide the object. Here is an example:
class Example {
public void one() {
System.out.println("one");
}
public void two() {
one(); // <<== #1
System.out.println("two");
}
public static void three() {
Example e = new Example();
e.one(); // <<== #2
}
}
On the line marked #1 above you call one() without specifying on what object you are calling it. Line marked #2, however, must specify the object on which the method is called.

This is an example of creating an object to serve as the calling object of the non static method.
public static void call() {
new Object().doSomething();
}
public class Object {
public void doSomething() {
// Your code to do something
}
}

Say you've got a class with two methods, one static and one non-static, like this:
class Simple {
public static void doStuff () {
doMoreStuff();
}
public void doMoreStuff() {
System.out.println("doing more stuff");
}
}
This won't compile since doStuff can't call the non-static method. However, the documentation you are referring to indicates that you can call a non-static method by creating an object to serve as the calling object. This means creating an instance of Simple, and then calling doMoreStuff on that instance:
class Simple {
public static void doStuff () {
Simple simple = new Simple();
simple.doMoreStuff();
}
public void doMoreStuff() {
System.out.println("doing more stuff");
}
}
This is a rather contrived example, but I often find it handy when working with the main method (which must be declared static) so that you aren't then declaring the rest of your methods static.

Related

Store references to instance methods in a static context

I would like to have a static map where the values are instance methods. Someting like:
public class MyClass {
static Map<MyEnum, Consumer<String>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, MyClass::firstMethod);
methodMapping.put(MyEnum.SECOND, MyClass::secondMethod);
}
void firstMethod(String param) {
...
}
void secondMethod(String param) {
...
}
}
This gives me an error saying "Non-static method cannot be referenced from a static context". I understand why this would be a problem if I would try to call the methods from the static context, but isn't it possible from an instance method to retrieve the method from the map and pass it this? Like:
MyClass.methodMapping.get(MyEnum.FIRST).accept(this, "string");
This is solvable as easy as changing Consumer to BiConsumer, turning the receiver instance of MyClass to a parameter of the function:
public class MyClass {
static Map<MyEnum, BiConsumer<MyClass,String>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, MyClass::firstMethod);
methodMapping.put(MyEnum.SECOND, MyClass::secondMethod);
}
void firstMethod(String param) {
...
}
void secondMethod(String param) {
...
}
void callTheMethod(MyEnum e, String s) {
methodMapping.get(e).accept(this, s);
}
}
You initialize methodMapping in a static initialization block. At that point, your instance methods can't be referred to yet because you haven't called new MyClass() yet.
You could fix this by either making your methods static, or moving the methodMapping initialization from the static block to a constructor.
PS: The keyword static can be omitted from the initialization block
isn't it possible from an instance method to retrieve the method from the map and pass it this
No. A Consumer only has a single parameter accept() method, so there's no such thing as "passing this at calling time".
You need an instance when creating the method reference, so this questions boils down to "can't call instance method from a static context".
It seems that you don't understand that
static Map<MyEnum, Consumer<String>> methodMapping;
static {
does exactly that, trying to call the methods from the static context where they don't exist.
The key thing to understand here: you intend to create a method reference; and a method reference needs some object to invoke that method on. Thus there is no "delaying"; there is no way in java to express "wait for this to be meaningful"; or in other words: there is no way in a static context to express: "you will be used in a non-static context later on; and then pick the corresponding this from there".
The key is to defer the specification of this or to be more specific: The particular instance on which a method is to be called. So instead of storing method references directly we store functions that accept an instance and return a method reference for that instance.
MyClass.java
public class MyClass {
static Map<MyEnum, Function<MyClass, Consumer<String>>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, t -> t::firstMethod);
methodMapping.put(MyEnum.SECOND, t -> t::secondMethod);
}
private String id;
public MyClass(String id) {
this.id = id;
}
void firstMethod(String param) {
System.out.println(id + ", 1st method, " + param);
}
void secondMethod(String param) {
System.out.println(id + ", 2nd method, " + param);
}
void dispatchMethod(MyEnum myEnum, String param) {
methodMapping.get(myEnum).apply(this).accept(param);
}
}
Main.java
public class Main {
public static void main(String[] args) {
MyClass instance = new MyClass("MyInstance");
MyClass.methodMapping.get(MyEnum.FIRST).apply(instance).accept("Using mapping directly");
instance.dispatchMethod(MyEnum.SECOND, "Using dispatch method");
}
}
Ideally methodMapping should be shielded against direct access from other classes so I'd suggest taking the dispatchMethod approach and making methodMapping private and immutable.

Java 8 - how to access object and method encapsulated as lambda

In Java you can "capture" a "method call on object" as a Runnable, as in belows example.
Later, having access to this instance of Runnable, is it possible to actually access the "captured" object and the method parameters of a method which is called (if possible this probably needs to be done via reflection).
For example:
class SomePrintingClass {
public void print(String myText) {
System.out.println(myText);
}
}
public class HowToAccess {
public static void main(String[] args) throws Exception {
final String myText = "How to access this?";
final SomePrintingClass printer = new SomePrintingClass();
Runnable r = () -> printer.print(myText); // capture as Runnable
inspect(r);
}
private static void inspect(Runnable runnable) {
// I have reference only to runnable... can I access "printer" here
}
}
Is it possible in the "inspect" method to access (probably via reflection) "printer" object and "myText" which was passed as a parameter?
It is possible, because the captured references are translated into fields of the runnable (as with all anonymous classes). The names will be not be consistent however.
I found by testing that you need to make myText non-final, otherwise it will be seen as a compile time constant and in-lined (and will not be accessible as a field):
private static void inspect(Runnable runnable) throws Exception {
for(Field f : runnable.getClass().getDeclaredFields()) {
f.setAccessible(true);
System.out.println("name: " + f.getName());
Object o = f.get(runnable);
System.out.println("value: " + o);
System.out.println("class: " + o.getClass());
System.out.println();
}
}
Prints:
name: arg$1
value: test.SomePrintingClass#1fb3ebeb
class: class test.SomePrintingClass
name: arg$2
value: How to access this?
class: class java.lang.String
With reflection, it is not possible to get local variables and method parameter values. Instead you can use AOP to intercept the method call and inspect the parameters.
Check if you want something as the below code where I have passed the runnable to a Thread object in your inspect method.
class SomePrintingClass {
public void print(String myText) {
System.out.println(myText);
}
}
public class HowToAccess {
public static void main(String[] args) throws Exception {
final String myText = "How to access this?";
final SomePrintingClass printer = new SomePrintingClass();
Runnable r = () -> printer.print(myText); // capture as Runnable
inspect(r);
}
private static void inspect(Runnable runnable) {
Thread t = new Thread(runnable);
t.start();
}
}
output will be:
How to access this?

Why can't I instantiate and create Object without main method? (Stack Overflow Error)

My Code:
(causes a Stack Overflow Error)
public class Overloads {
String uniqueID;
Overloads ov2=new Overloads();
public static void main(String[] args) {
System.out.println("IN MAIN");
}
public void setUniqueID(String theID) {
// II lots of validation code, and then:
uniqueID = theID;
System.out.println(uniqueID);
}
}
This Code Works Fine:
public class Overloads {
String uniqueID;
public static void main(String[] args) {
Overloads ov2=new Overloads();
System.out.println("IN MAIN");
}
public void setUniqueID(String theID) {
// II lots of validation code, and then:
uniqueID = theID;
System.out.println(uniqueID);
}
}
The presence of main method is not relevant here. The scope in which you have declared the variables, however, is very important.
Have you walked through what happens in the first version of the code?
Create new instance of Overloads
-> ov2 = Create new instance of Overloads
-> ov2 = Create new instance of Overloads
-> ov2 = Create new instance of Overloads
and so on. The variable ov2 is in scope of the class, thus it is initialized whenever an instance of the class is instantiated. This will never terminate until you run out of memory and get the stack overflow. Run it with a debugger for a clearer view.
The second version of the code only instantiates one instace of Overloads, in the scope of the main method. Thus creating one instance does not lead to the newly created instance creating new instance and so on..
You can do like this
public class Overloads {
String uniqueID;
static Overloads ov2 = new Overloads();
public static void main(String[] args) {
System.out.println("IN MAIN");
}
public void setUniqueID(String theID) {
// II lots of validation code, and then:
uniqueID = theID;
System.out.println(uniqueID);
}
}
this will create shared instance of Overloads, instantiation will be done only once, when class loaded

How to execute a particular function before main() in C and JAVA ?

I want to execute one function before main function in C and JAVA language.
I know one way that is, by using #pragma directive in C language. Is there any other way to do that in both languages?
I can think of two simple(-ish) ways to do it in Java:
Method #1 - static initializers
For example:
public class Test {
static {
System.err.println("Static initializer first");
}
public static void main(String[] args) {
System.err.println("In main");
}
}
Method #2 - A proxy main.
public class ProxyMain {
public static void main(String[] args) {
String classname = args[0];
// Do some other stuff.
// Load the class
// Reflectively find the 'public static void main(String[])' method
// Reflectively invoke it with the rest of the args.
}
}
You then launch this as:
java <jvm-options> ... ProxyMain <real-Main> arg ...
There is also a 3rd method, but it requires some "extreme measures". Basically you have to create your own JVM launcher that uses a different scheme for starting the application. Have this do the extra stuff before loading the entry point class and calling its main method. (Or do something different entirely.)
You could even replace the default classloader; e.g. How to change default class loader in Java?
in java you can use static block
public class JavaApplication2 {
static {
System.out.println("in static ");
}
public static void main(String[] args) {
System.out.println("in main ");
}
}
As an extension to the C standard gcc provides the function attribute constructor which allows functions to be called before main().
For details please see here (scroll down). Also this SO question and its answers help on this.
Try combining a static block and a static method containing what you want executed before your main method.
package test;
public class Main {
static {
beforeMain();
}
public static void main(String[] args) {
System.out.println("after");
}
private static void beforeMain() {
System.out.println("before");
}
}
Output:
before
after
It could be the first thing you call from your main function. That way it will run before your "real" main function.
Use that method(what you want to run before main method) as your main method.
Then it is so simple
Or use static block before main()
In java, execution of any other method is possible before main() method execution. We need a static initializer block for that. It starts with a static keyword.
Like:
static {
// statements
}
Now try to understand with actual code implementation.
public class BefourMain {
static int sum;
static {
sum = add(4,5,6);
System.out.println("Calling add() method: " + sum);
System.out.println("\ncalling main");
main(null);
System.out.println("Main end\n");
System.out.println("Now JVM calling main()\n");
}
public static void main(String[] args) {
int sum = add(1,2,3);
System.out.println(sum);
}
static int add(int a, int b, int c) {
return a + b + c;
}
}
Now try to understand with actual code implementation.
When we start executing this code the static initializer block will start execution first, in the static initializer block we are calling the add() method and storing the value in the static variable, and printing it. Next, we are calling the main() method, which will execute. when the static initializer block execution will complete JVM will call the main() method again.
Output
Output of the above code

AspectJ pointcut for constructor using java.lang.reflection

The following example is a reduction of the real problem in that it tries to simplify is as much as possible.
I have a java interface, and several objects that implement that interface, like:
public interface Shape{
public void draw();
public void erase();
public boolean isDrawn();
}
public class Square implements Shape{
#Override
public void draw(){
//TODO: method implementation
}
#Override
public void erase(){
//TODO: method implementation
}
Override
public boolean isDrawn(){
//TODO: method implementation
return false;
}
}
public Triangle implements Shape{
//same as above
}
public Circle implements Shape{
//same as above
}
This is the structure of my program. By using AspectJ I want to have a map that holds each object that implements the interface. To do so I was trying to capture the constructors by using the following aspect:
public aspect ShapeHolderAspect{
private Map<Integer, Shape> map = new HashMap<>();
private int count = 0;
pointcut shapeInit(): call((Shape+).new(..));
Object around(): shapeInit() {
System.out.println("capturing new");
Shape shapeType = (Shape)proceed();
map.put(++count, shapeType);
return shapeType;
}
}
This code will work if I create a Shape using the following scenario:
public static void main(String[] args){
Shape myShape = new Circle();
}
However, I am using java language reflection, and so technically I don't call the "new" constructor. Instead I locate the path of the package, and create the object passing a string with the name of the class:
public static void main(String[] args){
String shapeClassName = args[0];
Class<?> classType = Class.forName("myPackage.figures" + "." + shapeClassName);
Shape myShape =(Shape)classType.getConstructor().newInstance();
}
By doing this way, AspectJ cannot detect that I am creating shapes. How do I fix this?
New, better version:
Well, while the old version below actually catches all constructor executions, an around advice on constructor execution returns null because the object in question has not been initialised yet. So you would end up with a map of null pointers in your aspect. In order to fix this you need to bind this() to a variable (sample code uses default package name):
public class Application {
public static void main(String[] args) throws Exception {
new Circle().draw();
((Shape) Class.forName("Triangle").getConstructor().newInstance()).isDrawn();
((Shape) Class.forName("Square").getConstructor().newInstance()).erase();
}
}
import java.util.HashMap;
import java.util.Map;
public aspect ShapeHolderAspect {
private Map<Integer, Shape> map = new HashMap<Integer, Shape>();
private int count = 0;
after(Shape shape): execution(Shape+.new(..)) && this(shape) {
System.out.println(thisJoinPointStaticPart);
map.put(++count, shape);
}
after() : execution(* Application.main(..)) {
System.out.println("\nList of shapes:");
for (int key : map.keySet())
System.out.println(" " + key + " -> " + map.get(key));
}
}
The output looks like this:
initialization(Circle())
initialization(Triangle())
initialization(Square())
List of shapes:
1 -> Circle#1a2961b
2 -> Triangle#12d03f9
3 -> Square#5ffb18
BTW, if you absolutely need an around advice because you want to do other things before and after object creation, it would look like this:
void around(Shape shape): execution(Shape+.new(..)) && this(shape) {
System.out.println(thisJoinPointStaticPart);
proceed(shape);
map.put(++count, shape);
}
Old, incomplete version:
Quite simply, just intercept constructor execution instead of call:
pointcut shapeInit(): execution(Shape+.new(..));
This way you weave into the called code (callee), not the calling code (caller). Consequently, it does not matter if the caller issues a reflective or normal call.
Found that the following pointcut will do the job:
pointcut lockReflectInit(): call(public Object java.lang.reflect.Constructor.newInstance(..));
This will however catch ALL calls of newInstance, and not just the ones that return Shape =(

Categories

Resources