I was under the impression that private non-static variables could only be accessed by methods called on the object that the variables reside in, but this is not the case. Could someone please explain the reasoning behind why the following compiles and runs?
public class Sandbox {
private String _privateString = "unmodified";
public static void setPrivateString(String str, Sandbox s) {
s._privateString = str;
}
public String toString()
{
return _privateString;
}
public static void main(String[] args) {
Sandbox s = new Sandbox();
setPrivateString("modified", s);
System.out.println(s);
}
}
Output:
modified
EDIT: The same is true in C#.
Private member variables of class A can be accessed (i.e. read/written to) by any method of class A (static or non-static), so in your example, since the method changing the string is a method of the same class the member belongs to, it is granted access to the variable.
The reason is because a class is considered a self-contained body of logic (i.e. a specific implementation), so it makes sense that privacy is contained within a class; there is no reason to exclude static methods from that access right, since they are also part of the specific implementation the class provides.
You seem to be confusing visibility with scope. The instance variables are in the scope of an instance, so they cannot be accessed in a static method directly, but only with an instance reference qualifier: s._privateString in your case.
However, this does not mean that instance variables are not visible for a static method inside the same class, as private means visible inside the class (for any member with any scope).
The rule is simple:
member methods of a class can access and modify private members of the same class regardless of their visibility.
As mentioned in some other posts, Java's visibility system is class-based, not an object-based one.
Note that this is utilized in the compiler: When you have nested classes and you access a private field of the outer class, a public synthetic static method is generated to allow the access. It is usually named "access$0" etc. You can create a bytecode that violates encaplulation without the Reflection API by using these synthetic methods. You can also access them from the Reflection API without enabling access to private members. Many crazy things can be done...
If there was not such visibility system, compiler probably would need to compile it elsehow.
... Hoewver, the end-programmer usually don't need to know this detail. IDEs don't include synthetic methods in code completion and I hope that compilers (except Jasmin) don't allow you to use it. So if you don't generate bytecode and don't use Reflection API and you ignore these methods in the stacktrace, you probably don't need to know this detail.
Your code is compiled because inside setPrivateString(String str, Sandbox s) you are accessing the private variable _privateString by reference variable s.
A non-static member can only access by instance variable from the static API.
Check this code
public class Sandbox {
public static void main(String[] args) {
Sandbox s = new Sandbox();
// testAccess();// If you uncomment this line you will get compile time error
s.testAccess();//can only access in this way
}
private void testAccess() {
System.out.println("can only access by instance variable from static method");
}
}
Related
I just came across a code.In one case i am not able to access the private members of the class using its instance (which is fine) but in other case i am able to access the private members with its different instance (belongs to the same class). Can anyone please explain me why its happening?
class Complex {
private double re, im;
public String toString() {
return "(" + re + " + " + im + "i)";
}
Complex(){}
/*Below c is different instance, still it can access re,im( has a private access)
without any error.why? */
Complex(Complex c) {
re = c.re;
im = c.im;
}
}
public class Main {
public static void main(String[] args) {
Complex c1 = new Complex();
Complex c2 = new Complex(c1);
System.out.println(c1.re); /* But getting an error here ,
which is expected as re and im has a private access in Complex class.*/
}
}
You can access private members from any code block that is defined in the same class. It doesn't matter what the instance is, or even if there is any instance (the code block is in a static context).
But you cannot access them from code that is defined in a different class.
Your first reference is in the same class, Complex, which is why it works. And the second is in a different class, Main, which is why it doesn't work.
The reason is class Main cannot access to private fields of other classes. In this case to the private fields of Complex class.
You can access to private fields in Complex class only from methods in this class. In other words, if you move main method to Complex class the code will be compiled.
If you want to get/set values in Complex class from Main (or other classes) you should add setters/getters in Complex class.
Here is the table explaining access modifiers:
As you can see, in the private row, everything is N except for the column Class. That means you can access private members as long as you are accessing them in the same class as they are declared. You can even access private non-static members from a static context in the same class using an instance. There is no access modifier that only allows access from the same instance.
Why?
Because figuring out whether this and c are the same instance at compile time is a pain. You have to actually run the code to see if they are referring to the same instance or not.
Conceptually the access specifiers are # class level, not # instance level.
Following could be the reasons to keep access specifiers # class level.
From JLS Documentation, we can clearly see that the access is for users, who are implementing(or using a class/package) based on the contract.
To put in simple terms, as a developer(users) all I am concerned is what are the members(variables,methods) available, and what they do, how I can use them(the base of abstraction concept).
In your case, it is the same class and it has all the privilege to access its member and hence the observed behaviour.
Section 10.2 of Java conventions recommends using class names instead of objects to use static variables or methods, i.e. MyClass.variable1 or MyClass.methodName1() instead of
MyClass Obj1 = new MyClass();
Obj1.variable1;
Obj1.methodName1();
There is no explanation of the rationale behind this, although I suspect this has something to do with memory use. It would be great if someone could explain this.
I guess you mean "for static methods and variables".
There is no difference regarding memory, except of course if you create the instance just for calling the method. Conventions aren't for memory efficiency but for coder efficiency, which is directly related with the readability of the code.
The rationale is that by reading
MyClass.methodName1()
you know it's a static method and that it can't use or change your Obj1 instance.
And if you write
obj1.variable1; // note the "o" instead of "O", please do follow conventions
then the reader has to read your source code to know if variable1 is static or not.
If you use object for static variable access then compiler will replace it with Class Name only.
So
MyClass Obj1 = new MyClass();
Obj1.variable1;
Obj1.methodName1();
It is same as
MyClass.variable1;
MyClass.methodName1();
Now Why to differentiate? Answer is - It is for better reading If someone see method being called on Class then he immediately come to know that it is static method. Also it prevents generation of one additional object to access the method.
This has to do with public static methods and variables. Since these methods/variables are associated with the respective class rather than an instance of the class, it is nice to use refer to these methods or variables as className.methodName() or className.variableName
"Understanding Instance and Class Members" would be a good starting point to learn about the use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class
It is only because, public static method or public static variable is not associated with any object, but the class. Though the language designer has given the flexibility of invoking them on objects, reader of the code would be confused whether those are static variable/methods or instance methods/variables. So readability is the reason behind asking the developers to invoke them on classes.
You are allowed to access static members either by using the class name notation or by accessing using an object. It is not recommended to use the object notation since it can be very confusing.
public class TheClass {
public static final staticValue = 10;
public static void staticMethod() {
System.out.println("Hello from static method");
}
public static void main(String ... args) {
TheClass obj = null;
// This is valid
System.out.println(obj.staticValue);
// And this too
System.out.println(obj.staticMethod());
// And this is also valid
System.out.println(((TheClass)null).staticValue);
// And this too
System.out.println(((TheClass)null).staticMethod());
}
}
It is much clearer if the static methods and variables are called with the class name notation.
static variable belongs to the class and not to object(instance).
A static variable can be accessed directly by the class name and doesn’t need any object.
it saves space not having to have variables for the same data for each class.
Syntax : <class-name>.<variable-name>
public class AA{
static int a =10;
}
You can call
System.out.println(AA.a);
System.out.println(aObject.a);
There is no differen between two calling but maintain coding convention to keep more readbale
Is there an info-graphic that explains java variable inheritance and constructor code flow?
I'm having troubles visualizing how inheritance and class variables work, public, static private default or otherwise.
The Java Tutorials from Oracle have a section all about Inheritance and should be able to answer most of your questions.
I would refer you to go with Lava Language Specification and try to write the code using above keywords and then test it.
default: Visible to the package. .
private: Visible to the class only
public: Visible to the world
protected: Visible to the package and all subclasses .
The access modifier (public, protected, package) plays only a small role in inheritance. You can't make a function or variable in a subclass less accessible than the superclass (e.g., Animal has public void doStuff() and Cat extends Animal has private void doStuff()
Static and non-static methods don't really affect inheritance either. Static variables work the same way, except relative to the class of interest
public class Magic{
public static int pants;
}
public class MagicPants extends Magic{
public void go(){
System.out.println(pants);
System.out.println(MagicPants.pants);
System.out.println(Magic.pants);
}
public static void main(String argv[]){
Magic.pants = 2;
MagicPants.pants = 1;
new MagicPants().go();
}
}
All print 1
Constructor code flow is easy - follow the super() calls.
So i don't know graphics.
Static means the variable is the same for all object which have the same class.
Like
public Class TryVariable{
public static int variable = 2
public static void main(String[] args){
a = new TryVariable()
b = new TryVariable()
system.out.println(a.variable)
system.out.println(b.variable)
// both equals 2
a.variable= 3
system.out.println(a.variable)
system.out.println(b.variable)
// both equals 3, because variable is static.
}
Public variable means you can directly change directly her by the way i do in ma previous example: object.variableName = value.
This is dangerous, all people inadvisable to use it.
Private variable can't be change directly you need to use somes getters and setters to do this work. It's is the good way to code.
The defaut, i'm not sur of all parameters so i don't describe to you. But 99.9% of time the private is use.
Protected mean, the variable is open to packages and sub classes (in first time private is easier to use and safer)
An other parameter can be final, with this parameter the variable can't be change any more. It's like a constant. And a static final parameter is a class constant.
If you need more information, previous response explain where are find the officials sources.
This is very easy example: http://vskl.blogspot.cz/2009/05/polymorphism-in-java.html
every time you create Circle or Square object, Shape object is created too
About the variables:
- private fields are not accessible by any other class including subclasses.
- protected fields are accessible by any subclass. Taken the picture from the link, variables x and y of abstract class Shape, every instance of Circle or Square have these fields.
- default fields are accessible by any subclass and by any class in the same package(only in same package, classes in subpackages do not have access). This is useful typicaly when writing automated test, you don't have to declare public getter for the field.
- public fields are accessible by any other class. However using those is not a clean way how to write code, it is better to create private field with getter and setter.
- static keyword designates field owned by class, not by it's instances. It is like having one field shared by multiple instances of the class. If one instance changes value of this field, every other instance can read only this new modified
I have got the following java class. When I am calling the login method in my constructor, I access the static instance variable username using the class name, and the static instance variable password using the keyword this. My question is what is the difference between the two approaches? Which one should be used in what situation?
public class MyClass {
private Main main;
private static String username = "mylogindetails";
private static String password = "mypassword";
public MyClass(){
this.main = new Main();
this.main.login(MyClass.username, this.password);
}
public static void main(String args[]){
MyClass myclass = new myclass();
}
}
They are both equivalent.
However, accessing static members using this is misleading and should be avoided at all costs.
No difference.
Some feel that a static field or method should be accessed through the Class name, rather than through this or an instance, to highlight that it is a static. Eclipse, for example, has a config setting to flag a warning about a static resource being accessed through an instance reference.
My preferences, in order:
within the class itself, I would just reference the field without a qualifier
use the Class name
use this or an instance only if you feel the static nature of the field/method may change and it is a design detail that it is static that the clients of the class should not depend on (in which case, I would think about making it an instance method anyway to ensure how it is accessed)
There is no difference in this case, and I think it's compiled to the same bytecode (GETSTATIC).
But MyClass.username is preferred, because it reflects the nature of the field.
From Java Tutorial: Understanding Instance and Class Members:
Class variables are referenced by the
class name itself, as in
Bicycle.numberOfBicycles
This makes it clear that they are
class variables.
Note: You can also refer to static fields with an object reference like
myBike.numberOfBicycles
but this is discouraged because it does not make it clear that they are
class variables.
All instances of your class share the same password; password belongs to the class, not each instance, that's what static means.
So although you can access it from any instance, such usage is discouraged as it suggests the password is instance specific.
Remember that static variables are shared across all instances of your MyClass so using this to refer to them is misleading. Really it's just a style difference but you should not get in the habit of referring to it with this.
Well, static variables are not instance variables. Therefore , static instance variable is not a valid term.
You don't need to use either.
Because you've got an inner class you can directly access the static variable without an explicit reference to the outer class or to this
If using static fields is confusing, you can make them all caps to distinguish them. Often this is reserved for final static fields acting as constants though.
For my study in the university I'm forced to do some ugly java basics, like working without encapsulation, main method in the same class etc. (I do not want to open a discussion on a java styleguide, I just want to clarify, that I would not write something like this outside of the university)
I've stumbled across a behaviour that I can't explain to my self:
public class Person {
// fields
private int age;
public static void main(String[] args) {
Person foo1 = new Person();
foo1.age = 40;
System.out.println(foo1.age);
}
}
Why does this piece of code compile and run without error? How is it possible that I can access the private field? Strange behaviour due to having the main Method in the same class?
Because the static method main is a member of class Person and can thus access any private fields or methods in Person.
What are you worried about? That someone will write a class and then be able to access those methods from their own class?
If you're going to be concerned about anything, be concerned that you can access private fields in any class using reflection but even that's necessary for a lot of useful things.
Yes—in Java, private is class private not instance private.
Many other languages use instance private, eg Ruby and Smalltalk.
As your main method is in the same class and the instance variable is having private access it is only available to the methods of the same class. there is no access modifier which can restrict the methods of a same class to access its member variable. that is what happening here. if you have your main method in some other class though in the same package it would not have compiled.
You can access private fields from inside their class. That's the point of having them defined per-class.
You can write any other static method in the Person class and access the private variables from that method. Main is just a name. Such is life.
Because your method main(String[] args) is defined inside the class Person. If the method was defined outside the Person class you would not have been able to do that.