I am new to java hence probably a very noob question:
I have a class
public class Foo{
private static String foo;
private String bar;
public Foo(String bar){
this.bar = bar;
}
}
Now before I instantiate any object for class Foo, I want to set that static variable foo.
which will be used in the class..
How do i do this?
Also, please correct my understanding. value of foo will be same across all the objects, hence it does make sense to declare it as static ? right?
public class Foo{
private static String foo = "initial value";
private String bar;
public Foo(String bar){
this.bar = bar;
}
}
Since the value will be the same across all objects, static is the right thing to use. If the value is not only static but also never changing, then you should do this instead:
public class Foo{
private static final String FOO = "initial value";
private String bar;
public Foo(String bar){
this.bar = bar;
}
}
Notice how the capitalization changed there? That's the java convention. "Constants" are NAMED_LIKE_THIS.
foo will be shared among all instances of Foo
To initialize it:
Option A
private static String foo = "static variable";
Option B
private static String foo;
static {
foo = "static variable";
}
Option B is seldom used, mostly when there are some inter-dependencies between static variables or potential exceptions.
In either case, static init will happen when the class is loaded.
As stated by the other answers, you should set your initial value like so:
private static String foo = "initial value";
Additionally, if you want to access this variable from anywhere, you need to reference it in a static context, like so:
Foo.foo
where Foo is the class name, and foo is the variable name.
This is actually very useful in understanding the concept of static variables. Rather than referencing foo as a member of some instance of the Foo class, you are referencing foo as a member of the class itself. So, for all instances of Foo, the value of foo will be the same because it is owned by the class and not the instance.
Inside the Foo class, you can get away with just calling foo without qualifying it with a class name.
Related
I'm running into a problem when I compile my code. When I compile my code foo2.var returns null in class foo and I can't seem to figure out why. Is there something wrong in how I'm doing the static initialization in the foo2 class to cause foo2.var to be null in the foo class?
Any help is appreciated.
public class foo extends bar {
public final static String blah = foo2.var;
...
}
public abstract class bar {
...
}
public class foo2 extends bar {
public final static String var;
static {
var = "newstring";
}
...
}
Null pointer error on the foo2.var line in this example.
Accessing a static field (whose value is not a compile-time-constant expression) will trigger initialization of the class declaring that field, during which which the static initializers are executed. However, initialization is only guaranteed to have completed by the time the field is read if there is no cyclic dependency among initializers.
For instance, if you run the program
class Bar {
static final long bar;
static {
System.out.println("Assigning bar");
bar = Foo.foo;
}
}
class Foo extends Bar {
static final long foo;
static {
System.out.println("Assigning foo");
foo = 1;
}
}
public class Test {
public static void main(String[] args) {
new Foo();
System.out.println(Bar.bar);
}
}
you get the following output:
Assigning bar
Assigning foo
0
1
because to create a new instance of Foo, Foo.class is initialized, which first initializes its super class Bar.class, which reads the field of Foo.class, but Foo.class is already being initialized. The Java Language Specification mandates in section 12.4.2, step 3, that such a recursive initialization completes immediately, i.e. the caller will see the class in a partially initialized state. That is, Foo.foo is unassigned at the time it is read, and therefore still contains the default value of 0. That value is assigned to Bar.bar, completing initialization of Bar.class. Then, initialization of Foo.class is resumed by running the initializer, which sets Foo.foo to 1.
Practically speaking, you might wish to review the dependencies of your classes and structure your program such that there are no cyclic dependencies among initializers.
You have not specified a type for var try public final static String VAR;
and then why not just
public class foo2 extends bar {
public final static String var = "newstring";
var doesn't have a type. Also constants in Java are uppercase by convention. Make it:
public class Foo2 {
public final static String VAR;
static {
VAR = "newstring";
}
...
}
You are missing a type for var, change that line to the following:
public final static String VAR;
Specify var type.
Also, by coding convention class names should be written in CamelCase and constants, UNDERSCORED_CAPS
public class Foo2 {
public final static VAR = "newstring"; // why not?
...
}
Also, you may shadow foo2 class by some variable. Check your imports. Because class static field reference cannot produce NPE!
public class Foo{
public Foo(){}
public void Method()
{
this = null; //doesn't work
}
}
I know that in C# i can't do this, but may be can in Java?
nope , you can not do.
you will get below error.
The left-hand side of an assignment must be a variable
Can i delete instance of class from method of this class?
There is no instance of the class yet unless you've created it.
Foo foo=new Foo();
You can dereference foo by
foo=null;
Now the foo object which the foo reference points to on the heap will be collected by garbage collector
public class Foo{
public static void main(String[] args)
{
Foo foo=new Foo();
System.out.println(foo);
foo=null;
System.out.println(foo);
}
}
Output
Temp#1a8c4e7
null
Can i delete instance of class from method of this class?
No. Because it doesn't make sense right. You didn't create any object so far and you are trying to dereference it..??
In Java, Memory management is handled by JVM and all the objects are destructed by JVM when they are no more referenced.
So you can not guarantee an instance to be deleted at specific time.
public class Foo {
public Foo() {
}
public void Method() {
// some code
}
}
public class Test {
public static void main(String[] args){
Foo foo = new Foo(); // Constructor-Instance created and referenced
foo = null; // reference variable foo is made null.
}
}
Once foo is made null, the instance for Foo is available for GC.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
Suppose I have a class and constructor called TestClass.
public class TestClass {
Foo foo;
public TestClass(Foo foo) {
this.foo = foo;
}
}
Here, the constructor accepts an object which is an instance of class Foo. Suppose my static void main(String[] args) does the following, completely separate from any TestClass;
(1) Instantiate foo
(2) Pass instance foo to TestClass constructor
(3) Change the internal state of foo
After step (3), will the foo within my instance of TestClass also have its state changed?
It is not passed by reference. Rather, it is passed by value of the reference, which is a subtle but important distinction.
After you mutate foo in the rest of your main() method, the foo field will also exhibit these mutations, as you state, since both variables point to the same instance. However, if you reassign foo to something new, the foo field will not be changed. This would not be true if foo were truly passed by reference. In short, everything is passed by value in Java; it just so happens that objects are dealt with by reference, and so the values of these references are passed.
I'll try to illustrate this with an example. Consider the following class:
class A {
public int n;
public A(int n) {
this.n = n;
}
}
and the following method:
public static void mutate(A a) {
a.n = 42;
}
Now we can have something like this:
A a = new A(0);
A.mutate(a);
System.out.println(a.n);
42
We can see that the state of a was changed in mutate(). Now let's modify the static method:
public static void mutate(A a) {
a = new A(42);
}
and try again:
A a = new A(0);
A.mutate(a);
System.out.println(a.n);
0
As you can see, the state of a is unchanged. If the reference had been passed to the function, we would expect the effect of the reassignment to be evident beyond the scope of the method. Nevertheless, some reference was in fact passed, since mutating the argument caused changes outside of the method as well.
Yes, because you are assigning same object to another reference of Foo class, i.e. object is same, but being referred by two reference.
After step (3), will the foo within my instance of TestClass also have
its state changed?
Yes.
You might like to take a read through this
Updated...
Now, assuming you pass the constructor a primitive value...
public class TestClass {
int foo;
public TestClass(int foo) {
this.foo = foo;
}
public String toString() {
return "TestClass: " + foo;
}
}
public static void main(String args[]) {
int myFoo = 1;
TestClass test = new TestClass(myFoo);
myFoo += 2;
System.out.println("myFoo = " + myFoo);
System.out.println("yourFoo = " + test);
}
This will output...
myFoo = 3
yourFoo = 1
Which demonstrates the fact that changing the value of a primitive does not change the value maintained by the constructor/method.
Equally, if you change the object reference after you pass it
public class TestClass {
Foo foo;
public TestClass(Foo foo) {
this.foo = foo;
}
public Foo getFoo() {
return foo;
}
}
public static void main(String args[]) {
Foo myFoo = new Foo();
TestClass test = new TestClass(myFoo);
myFoo = new Foo();
System.out.println("myFoo == yourFoo = " + myFoo.equals(test.getFoo()));
}
Will output
myFoo == yourFoo = false
As the object references are not the same.
When are variables at the top of the class initialized in comparison to the constructor?
Sorry, this is what I meant:
public class aClass {
private int num;
public aClass {...}
Default values (null for object fields, 0 etc. for primitive fields`) are technically never explicitly assigned as far as the emitted bytecode is concerned. (This is done "internally" during object instantiation, before any initializer/constructor code runs.)
Explicit initializer code for instance fields is "copied" at the start of every constructor, after a superclass constructor call (if there is any) in the class by the compiler. The code sample:
class Foo {
int bar = 123;
public Foo() {
// ...
}
public Foo(int bar) {
this.bar = bar;
// ...
}
}
is compiled into bytecode equivalent to:
class Foo {
int bar;
public Foo() {
this.bar = 123;
// ...
}
public Foo(int bar) {
this.bar = 123;
this.bar = bar;
// ...
}
}
Same goes for initializer blocks. This means these variables get initialised before any normal constructor code executes.
Members defined with values are initialized in the constructor, just like any other members. But it's not exactly the constructor you wrote; Java changes each constructor behind the scenes by inserting member initializers and initializer blocks in the beginning of it. You could view it as the members getting initialized just before the constructor, if you want to view it temporally.
Effectively, you can consider them initialized before your constructor gets called. So if you have:
class Dog {
private String voice = "woof";
public Dog() {
System.out.println(voice);
}
}
You'll get "woof" printed to the console successfully, rather than null.
Considering that simple java code which would not work:
public class Bar extends AbstractBar{
private final Foo foo = new Foo(bar);
public Bar(){
super(foo);
}
}
I need to create an object before the super() call because I need to push it in the base class.
I don't want to use an initialization block and I don't want to do something like:
super(new Foo(bar)) in my constructor..
How can I send data to a base class before the super call ?
If Foo has to be stored in a field, you can do this:
public class Bar extends AbstractBar{
private final Foo foo;
private Bar(Foo foo) {
super(foo);
this.foo = foo;
}
public Bar(){
this(new Foo(bar));
}
}
Otherwise super(new Foo(bar)) looks pretty legal for me, you can wrap new Foo(bar) into a static method if you want.
Also note that field initializers (as in your example) and initializer blocks won't help either, because they run after the superclass constructor. If field is declared as final your example won't compile, otherwise you'll get null in superclass constructor.
thats not possible in java. the only possible solution is the new call in the super constructor.
if the foo object can be shared between instances you may declar it as static
public class Bar extends AbstractBar{
private static final Foo foo = new Foo(bar);
public Bar(){
super(foo);
}
}
if the super class is under your control, you can refactor it and use the template method pattern to pull the object into the constructor instead of pusing it from the subclass. this applys the hollywod principle: don't call us, we will call you ;)
public abstract class AbstractBar{
private Object thing;
public AbstractBar(){
this.thing = this.createThatThing();
}
protected abstract Object createThatThing();
}
public class Bar extends AbstractBar {
// no constructor needed
protected Object createThatThing(){
return new Thing();
}
}
class AbstractBar{
public AbstractBar() {
}
public AbstractBar(Foo t) {
}
}
class Bar extends AbstractBar{
static Foo t=null;
public Bar() {
super(t=new Foo());
}
}
class Foo{...}