I seen this bit of code, Even though I think I got the concept of static in Java I am bit confused. Can any one explain it to me, how an object being static works?
My code:
package com.oracle.certification.sampleTest;
public class Person {
static class Mail {
static String desc="Male";
}
static Gender Mail=new Gender();
}
package com.oracle.certification.sampleTest;
public class Gender {
String desc="Gender";
}
package com.oracle.certification.sampleTest;
public class Human {
public static void main(String str[]) {
System.out.println(Person.Mail.desc);
}
}
When the class Human is run, the O/P is 'gender' not 'male', even though des= gender is nonstatic and des=male is static with static inner class. Also I don't need to import the classes in Hman? I am sorry that I have very little knowledge about inner classes, first of all.
Can any one explain it to me, How an object being static works?
Essentially, static in that context means that the entity in question is attached to the class itself, not to an object of the class. Hence, with static there is exactly one instance of what you declare:
class T {
public static int staticMember = 0; // one variable stored in memory
public int nonStaticMember = 0; // as many variables stored in memory as objects are created from the class
}
See also What does the 'static' keyword do in a class?
However, your question is not necessarily a misunderstanding of static classes, but a corner case of name resolution: You are declaring both a type and a member variable with the same name (Mail) in one scope (within the Person class) - while one might think that this should not even be possible, the Java language does allow this and defines a couple of rules to determine which one to use.
From the JLS:
A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package. In these situations, the rules of §6.5 specify that a variable will be chosen in preference to a type.
...
static class Mail { // a Type
}
static Gender Mail ... // a Variable with the same name
// - the compiler chooses to use this one
...
Hence, when referencing Person.Mail, the compiler chooses the variable, not the type (the inner class).
Related
I am new to Java and am wondering how to create in an elegant way a global object whose members are constant. One way to do this is:
public class Global {
public final static String NAME = "John Doe";
public final static int AGE = 100;
}
and then calling it outside as
import Global;
public static void main(String[] args) {
int age = Global.AGE; // works fine; age cannot be modified
}
The only issue is: I have a lot of variables in this class that I'm copying from a text file and adding the keywords "static", "public", and "final" is cumbersome and makes it look ugly. I know it's not a big issue, but I would like a more elegant solution to this. Any ideas? I have tried nested classes but could not figure out to have it behave correctly.
If you are sure that you will handle only constants you can declare your class as final class and define a private constructor - Doing that, you avoid instantiation (the assertion error will make the class safe even if they try to instantiate the class using reflection), this is an elegant way to consolidate your constants in a class.
public final class Global {
public static final String NAME = "John Doe";
public static final int AGE = 100;
}
private Global() {
//this prevents even the native class from
//calling this constructor as well :
throw new AssertionError();
}
Advantages:
Since the required static memebers are imported statically, the class namespace is not polluted.
The compiled code has one fewer binary compatibility constraint (that “class implements Constants Interface”).
Because static imports apply only to the current file (and not the whole class hierarchy), it is easier to discover where each static member is declared.
Run-time and compile-time semantics are more closely aligned when using static imports instead of constants interfaces.
If required, static blocks can be declared.
Since some answers are suggesting using the interface, I suggest you check out this article Why the Constant Interface Pattern Should Be Discouraged. If you can check out the Effective Java book will be a good reference as well.
You can use interface also
public interface Global {
String NAME = "John Doe";
int AGE = 100;
}
I have the following two classes (in two separate files).
public class Foo
{
public static class A
{
public static final boolean FLAG = false;
}
public final A A = new A();
}
public class Bar
{
void method()
{
if (Foo.A.FLAG) <<<< this is giving "Cannot make static ref to non-static field
// do something
;
}
}
My question is, why isn't the compiler able to recorgnise that by Foo.A, I meant the class A, not the member, which also happens to be named A?
This is called obscuring, an obscure feature/limitation of Java
A simple name may occur in contexts where it may potentially be
interpreted as the name of a variable, a type, or a package. In these
situations, the rules of §6.5 specify that a variable will be chosen
in preference to a type, and that a type will be chosen in preference
to a package. Thus, it is may sometimes be impossible to refer to a
visible type or package declaration via its simple name. We say that
such a declaration is obscured.
If the variable A was static, it would compile since you can can access static members on object references.
Also FLAG hasn't been initialized.
Some ways to access the flag:
<Foo_A extends Foo.A> void test1()
{
if(Foo_A.FLAG)
;
}
void test2()
{
class Foo_A extends Foo.A{}
if(Foo_A.FLAG)
;
}
-------------------------------------
import pkg.Foo.A;
public class Bar
{
void test3()
{
if(A.FLAG)
;
}
}
in these contexts, "Foo.A" can only be interpreted as a type, not a variable.
Because inner classes require an instance of the enclosing type. If you dont have an instance of Foo, A doesnt exist.
Edit - This is incorrect, but the reason why is informative. see the comments below:
According to Java, static variable are accessible by Class name but they are also accessible by class object even though Java don't suggest it, and it gives the same answer.
I know there will be only one copy of the variable and its value will be same for all objects and other things. Why does Java suggest to use class name instead of class object?
Because it can be confusing! There is no dynamic dispatching on static members.
Take a look at this confusing code: (might be syntax errors; my Java is rusty)
public abstract class Singer {
public static void sing() {
System.out.println("Singing");
}
}
public class Soprano extends Singer {
public static void sing() {
System.out.println("Singing in the range of C4-A5");
}
}
public class MyDriver {
public static void main(String[] argv) {
Singer mySoprano1 = new Soprano();
Soprano mySoprano2 = new Soprano();
mySoprano1.sing();
mySoprano2.sing();
}
}
Looking at MyDriver it's confusing because it seems like the sing method is polymorphic so the output should be...
Singing in the range of C4-A5
Singing in the range of C4-A5
... because both soprano1 and soprano2 are instances of Soprano - not Singer.
But alas, the output is actually:
Singing
Singing in the range of C4-A5
Why? Because there is no dynamic dispatch on static members, so the declared type of mySoprano1 determines which sing method is invoked... and the declared type of soprano1 is Singer, not Soprano.
For more, check out Puzzle 48 "All I get is static" in the book Java Puzzlers.
It is more self-documenting if you write MyClass.staticVariable than myObject.staticVariable. It tells the person looking at the code that staticVariable is a property of MyClass, as opposed to myObject which is a particular instance of the class.
One point I can think is if you use Class Reference instead of Object, JVM does not need to create a new Object at all to access that static variable. This is a good programming practice for performance.
I have the following two classes:
public class Class1
{
public Class1 randomvariable; // Variable declared
public static void main(String[] args)
{
randomvariable = new Class1(); // Variable initialized
}
}
public class Class2
{
public static void ranMethod()
{
randomvariable.getSomething(); // I can't access the member "randomvariable" here even though it's public and it's in the same project?
}
}
I am very certain that it's a very fundamental thing I'm missing here, but what am I actually missing? The Class1 member "randomvariable" is public and so is the class and both classes are in the same project.
What do I have to do to fix this problem?
There are two problems:
Firstly, you're trying to assign a value to randomvariable from main, without there being an instance of Class1. This would be okay in an instance method, as randomvariable would be implicitly this.randomvariable - but this is a static method.
Secondly, you're trying to read the value from Class2.ranMethod, again without there being an instance of Class1 involved.
It's important that you understand what an instance variable is. It's a value associated with a particular instance of a class. So if you had a class called Person, you might have a variable called name. Now in Class2.ranMethod, you'd effectively be writing:
name.getSomething();
That makes no sense - firstly there's nothing associating this code with Person at all, and secondly it doesn't say which person is involved.
Likewise within the main method - there's no instance, so you haven't got the context.
Here's an alternative program which does work, so you can see the difference:
public class Person {
// In real code you should almost *never* have public variables
// like this. It would normally be private, and you'd expose
// a public getName() method. It might be final, too, with the value
// assigned in the constructor.
public String name;
public static void main(String[] args) {
Person x = new Person();
x.name = "Fred";
PersonPresenter.displayPerson(x);
}
}
class PersonPresenter {
// In a real system this would probably be an instance method
public static void displayPerson(Person person) {
System.out.println("I present to you: " + person.name);
}
}
As you can tell by the comments, this still isn't ideal code - but I wanted to stay fairly close to your original code.
However, this now works: main is trying to set the value of an instance variable for a particular instance, and likewise presentPerson is given a reference to an instance as a parameter, so it can find out the value of the name variable for that instance.
When you try to access randomvariable you have to specify where it lives. Since its a non-static class field, you need an instance of Class1 in order to have a randomvariable. For instance:
Class1 randomclass;
randomclass.randomvariable.getSomething();
If it were a static field instead, meaning that only one exists per class instead of one per instance, you could access it with the class name:
Class1.randomvariable.getSomething();
I'm learning Java and I just wonder why public and private is used when a method or members is static? When static is used they are class methods and class members and could be used from other classes without creating an object, so is public and private necessary? Some help is preciated to understand. Sorry if this question is too simple for some.
The accessibility of a field or method is orthogonal to the fact that it's static or not.
You could have a static method accessible from the outside, and a static method that must only be used from inside the class itself (by other static or non-static methods). The same goes for fields.
For example:
// not visible from the outside
private static final long MILLISECONDS_IN_A_MINUTE = 1000L * 60 * 60;
public static Date addMinutes(Date d, int amount) {
return addMillis(d, MILLISECONDS_IN_A_MINUTE * amount);
}
// not visible from the outside
private static Date addMillis(Date d, long amount) {
return new Date(d.getTime() + amount);
}
It's not necessary, but there can be static methods and data members for internal use only.
An example for this is if you want an unique id for every instance of the class:
class Foo
{
private static int nextId = 0;
private static int generateId() { return ++nextId; }
private int id;
public Foo()
{
id = generateId();
}
}
As you can see, nextId and generateId() are not needed outside the class, nor should they be used outside the class. The class itself is responsible for generating id's. But you need them to be static (well, you need nextId to be static, but you can also make generateId() static since it doesn't access non-static members).
Whenever an object Foo is created, the static counter is incremented, thus you get different ids for each instance of the class. (this example is not thread-safe)
Suppose you have a static public method and this method must access to a private attribute. This private attribute must be static too. There's one reason why private static exists.
Example :
public class Test {
private static int myattr = 0;
public static void foo() {
myattr = 2;
}
}
Above, myattr must be a static attribute in order to use it in the foo() method.
Yes it is needed.
If you have a Static Method and want to use a private variables in that method, then you need to declare it static too.
Or you want the static variables not be visible to other packages, then don't declare it public.
From what I remember, it's not really needed. But public means, basically in any programming language, that it can be used by outside files. With private it can only be used within that file, and static means you cannot change the value of said reference. Whether these be functions, or variables, the same rules apply. I might be off. Haven't done Java in about a year and a half.
The ways you can incorporate these types is up to you. After all, a program is only as diverse as it's user. ^_^
Public and private keywoards have to do with visibility: which members do you want to accessible to other classes and which should be hidden or encapsulated.
Static members relate to the class as a whole, while non-static members operate on object instances.
I'm learning Java and I just wonder why public and private is used when a method or members is static?
I believe your question is due to a common misconception that the access modifiers are for instances, but they're not!
Two different instances can access each others private members if they are of the same class.
In other words, the access modifiers works on class level. Since also static members belong to some class, it makes sense to have access modifiers also on them.
A static method (or variable) that should only be used by code in the same class (as in the example by JB Nizet) should be private, while a static method or variable that may be used by code in any class should be public.
When the static is used with methods it doesn't only mean that it should be used by the members of other classes.
The case when we access the static methods of a class is one when
the class (which contains the method) cannot be instantiated i.e. no objects can be created of that class.
There may be situations when two different classes may have static methods with same name. In that case you want to use the method of the same class not the method of other class.