I have recently played with code in java, and encountered this problem, that the code inside the constructor seems to be not executed, as the compiler throws the NullPointerException.
public class ObjectA {
protected static ObjectA oa;
private String message = "The message";
public ObjectA() {
oa = new ObjectA();
}
public static void main(String args[]) {
System.out.println(oa.message);
} }
Now when i move the creation of the object before the constructor, i.e. I do it in one line, then everything works fine.
Can anyone explain to me why does this happen, and where my understanding of the code is wrong?
Thanks in advance.
You're never calling the ObjectA() constructor, except in the ObjectA constructor. If you ever did call the constructor (e.g. from main), you'd get a stack overflow because you'd be recursing forever.
It's not really clear what you're trying to do or why you're using a static variable, but your code would be simpler as:
public class ObjectA {
private String message = "The message";
public static void main(String[] args) {
ObjectA oa = new ObjectA();
System.out.println(oa.message);
}
}
Also note that the compiler never throws an exception. It's very important to distinguish between compile-time errors (syntax errors etc) and execution-time errors (typically exceptions).
You need to move ObjectA oa = new ObjectA() to your main method.
Also, there is no need for this: protected static ObjectA oa;
You should copy/paste a Hello World program from a tutorial and see how it works.
You define a static variable oa but you only ever intialise it in the class's constructor. You never instantiate your class ObjectA so oa can only ever be null.
When you call your main method it tries to access the message variable of a null object, hence the NPE.
1) You never create an object
put:
ObjectA oa = new ObjectA();
in your main before your System.out.print.
2) set the message to public instead of private.
Hope something you need like this
public class ObjectA {
protected static ObjectA oa;
private String message = "The message";
public ObjectA() {
}
public static ObjectA getInstance() {
if (oa == null) {
oa = new ObjectA();
}
return oa;
}
public String getMessage() {
return message;
}
public static void main(String args[]) {
System.out.println(ObjectA.getInstance().getMessage());
}
}
Related
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.
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
As they say System is final class which have out of type PrintStream as a field member and println is method in PrintStream class.
I created a class UseNumber with static field no of type Number and just wanted to access a method of Number class but it is throwing NullPointerException
public class Number {
private int first;
private int second;
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
}
and for UseNumber Class
public class UseNumber {
private static Number no;
public static void main(String[] args) {
UseNumber.no.setFirst(12); //throwing nullpointer exception here
UseNumber.no.setSecond(22);
System.out.println(UseNumber.no.getFirst()+UseNumber.no.getSecond());
}
}
Re: NullPointerException
setFirst is not a static method and it requires an instance of Number. You didn't create one. You just declared a Number variable called no. Since it's initialized to null by default, you're getting a NullPointerException.
One way to fix it:
private static Number no = new Number();
The variable no being declared as static inside UseNumber simply means you will be able to access this object without an instance of UseNumber. But this static declaration won't cascade down to the methods of no. They will still require an instance, as emphasized by the error you're getting.
Re: System.out
out is a static member of System - but it's an instantiated object already.
In fact, if you view the code of System, you'll find this line:
out = com.ibm.jvm.io.ConsolePrintStream.localize(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)), true);
So when you say:
System.out
System will give you the its initialized PrintStream object called out. In essence, System.out.println is just a shortcut for this:
PrintStream p = System.out;
p.println();
A nullpointerException is thrown when you attempt to access a null object by the "." operator.
In the line you indicated the exception is thrown, the no object is null and you are trying to access its setFirst method which will of course throw a nullpointer exception.
to fix the error, initialize your no object, maybe like this :
public class UseNumber {
private static Number no;
public static void main(String[] args) {
UseNumber.no = new Number(); // Initialize here your no object
UseNumber.no.setFirst(12); //This line will no longer throw an exception.
UseNumber.no.setSecond(22);
System.out.println(UseNumber.no.getFirst()+UseNumber.no.getSecond());
}
}
Maybe you can write a interface method to get the instance of no. In the method you can check if it's null, similar to the way we do with Singleton pattern.
public class UseNumber {
private static Number no;
public static getNumberInstance() {
if(no == NULL) {
no = new Number(); //This will get executed only once, for first call.
}
return no;
}
public static void main(String[] args) {
UseNumber.getNumberInstance().setFirst(12);
UseNumber.getNumberInstance().setSecond(22);
System.out.println(UseNumber.getNumberInstance().getFirst()
+UseNumber.getNumberInstance().getSecond());
}
}
I have three classes.. A,B,C.
In both classes B and C i have a static string variable "name" which contains the name of B and C, as-
class B
{
static name;
public static void main(String args[])
{
name="Class B";
A.getName();
}
I am calling class A's getName method from class B and C.. Class A is as follows:
class A
{
getName()
{
System.out.println(this class called me);
}
}
class C is:
class C
{
static name;
public static void main(String args[])
{
name="Class C";
A.getName();
}
Now my question is, what code should i use in place of "this class called me" in class A so that i get the name of whichever class calls A! I hope i am clear!!
Your A.getName method cannot know what class's code called it. You have to pass that information into it.
Okay, so that's not strictly true, you could figure it out by generating a stack trace and inspecting that. But it would be a very bad idea. In general, if a method needs to know something, you either A) Make it part of an instance that has that information as instance data, or B) Pass the information into it as an argument.
class A {
getName()
{
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
int lastStackElement = stackTraceElements.length-1;
String callingObjectsName = stackTraceElements[lastStackElement].getClassName();
System.out.println(callingObjectsName + " called me.");
}
}
Modify your code to something like this:
class A
{
getName(String className)
{
System.out.println(className);
}
}
and use it like :
class B
{
static name;
public static void main(String args[])
{
name="Class B";
A.getName(name);
}
}
It sounds like what you're really trying to do is to pass information from one stack frame to another one -- and specifically, from a frame A to a frame B, where A invoked B. This is an easy thing to do, and I think you're over-engineering it.
public class B {
static String name = ...
public static void main(String[] args) {
A.getName(name);
}
}
public class C {
static String name = ...
public static void main(String[] args) {
A.getName(name);
}
}
public class A {
public static void getName(String name) {
System.out.println(name);
}
}
Your approach would require:
Getting the stack trace
Using that to get the calling stack frame, which is element 1 in the stack trace array
Using that to get the class name for the calling method
Using Class.forName to get the Class<?> object
Calling getField("name") on that Class<?> object to get a Field object
(optional but recommended) Confirming that the Field represents static field of type String
calling get(null) on the Field to get its value (the null represents the object for which you want the field -- since the field is static and thus not tied to any object, this argument is ignored), and casting this value down to String
Or, instead you could:
Just pass the name to the function that needs it.
Your approach also requires that the name field be static, since there's no way to get the calling instance (even though you can get the calling instance's class). The simpler approach works even if name is an instance field.
What is the difference between ClassName.m() and (new ClassName()).m() m() is a static method.
The difference is that in your second example you are creating an unnecessary object in memory.
It is still calling the same static method for the ClassName class.
It is recommended to use ClassName.m() to avoid unnecessary object creation and to provide context to the developers indicating that a static method is indeed being called.
Three things:
The second has an extra call, which means it might change the outcome. This may be bad, may not, but it is something to consider. See example on how this can work.
The second creates an extra object. That's bad.
The second implies you're calling a method on an object, not on the class itself, which confuses people who read it. That's also bad. See example for how this can be very bad!
Consider the following, reason 1:
class ClassName {
static int nextId;
static int m() { return nextId; }
int id;
ClassName() { id = nextId; nextId++; }
/**
C:\junk>java ClassName
2
2
3
*/
public static void main(String[] args) {
new ClassName();
new ClassName();
System.out.println(ClassName.m());
System.out.println(ClassName.m());
System.out.println((new ClassName()).m());
}
}
Consider the following, adding on to reason 2, as alluded to by #emory:
class ClassName {
// perhaps ClassName has some caching mechanism?
static final List<ClassName> badStructure = new LinkedList<ClassName>();
ClassName() {
// Note this also gives outside threads access to this object
// before it is fully constructed! Generally bad...
badStructure.add(this);
}
public static void main(String[] args) {
ClassName c1 = new ClassName(); // create a ClassName object
c1 = null; // normally it would get GC'd but a ref exist in badStructure! :-(
}
}
Consider the following, reason 3:
class BadSleep implements Runnable {
int i = 0;
public void run() {
while(true) {
i++;
}
}
public static void main(String[] args) throws Exception {
Thread t = new Thread(new BadSleep());
t.start();
// okay t is running - let's pause it for a second
t.sleep(1000); // oh snap! Doesn't pause t, it pauses main! Ugh!
}
}
From an external observer's perspective, there's no difference. Both ways result in a call to the method which can only do the exact same thing in either case. You should never do the second one, though, as it just doesn't make sense to create an object in that case.
If m() is a static method, it's generally correct practice to use ClassName.m() since m() is a method of ClassName, not an object of ClassName.