Clarification of private access modifier [duplicate] - java

This question already has answers here:
Do objects encapsulate data so that not even other instances of the same class can access the data?
(7 answers)
Closed 9 years ago.
I am trying out the following code from Ivor Horton's Java book in which a two dimensional point is implemented via a simple class.
public class Point
{
//x and y coordinates
private xVal,yVal;
//Constructor
public Point (double x, double y)
{
this.xVal = x;
this.yVal = y;
}
//Constructor
public Point (final Point aPoint)
{
this.xVal = aPoint.xVal;
this.yVal = aPoint.yVal;
}
}
Now, the point I don't understand is that in the second constructor which takes an object of type Point as argument, the newly created Point object can access the instance variables x and y of argument Point object directly. This means that private members(methods and variables) of an object can be accessed from inside methods of another object of the same type, in addition to the methods inside the same class. Can anyone please clarify the issue because according to my understanding, the variables of the arugment object should be accessed via getter and setter because they are private.

This is the common misconception that private fields are accessible only by the same instance.
Actually, private fields are private within that class, and not for an instance. So any instance of that class can access private field when in that class.
From JLS - Section 6.6.1:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Emphasis mine.

It is private to the class, rather than private to the object.
This means other instances of the class can access private variables within an object of the same class.
The docs don't make this immediately obvious - but they do talk about access depending on class, rather than on object :
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

First of all there's an error in the code.
should be:
public class Point
{
//x and y coordinates
private xVal,yVal;
//Constructor
public Point (double x, double y)
{
this.xVal = x;
this.yVal = y;
}
//Constructor
public Point (final Point aPoint)
{
this.xVal = aPoint.xVal;
this.yVal = aPoint.yVal;
}
}
Note the second C'tor aPoint variables.
Secondly, private means private to the Class. Not the instance.
So other instances of the class can access the private members/methods.

From javadocs:
The private modifier specifies that the member can only be accessed in
its own class
You an always access private members of the class within the class anywhere including constructors.

This means that private members(methods and variables) of an object
can be accessed from inside methods of another object of the same type
Yes, this is correct. The "private" access modifier works on file level.
This means you can not only access private members from different objects but even from a different class, if one class is a nested (static or non-static), local or anonymous class of the other and if you have a valid object reference of the other class (either explicit or implicit). This works in both directions (outter <-> inner).

Note that the purpose of access restriction is making explicit the scope and range of the coupling between parts of code.
Seen in this light, private members of a class/instance should be accessible to all code enclosed by the declaration of that class—and indeed they are.

Related

Can't use class methods after initializing class [duplicate]

public class RoundCapGraph extends View {
static private int strokeWidth = 20;
public void setStrokeWidth(int strokeWidth){
this.strokeWidth = strokeWidth;
//warning : static member 'com.example.ud.RoundCapGraph.strokeWidth' accessed via instance reference
}
}
In android studio I'm trying to set strokeWidth using setStrokeWidth.
But I get warning
static member 'com.example.ud.RoundCapGraph.strokeWidth' accessed via instance reference
Question : Does 'this' keyword make new instance and access variable via new instance?
EDITED : I don't really need to set strokeWidth variable static, but I want to understand why using 'this' keyword produce particular warning
this keyword doesn't create a new instance, but this. is usually used to access instance variables.
Therefore, when the compiler sees that you try to access a static variable via this., it assumes that you might have made a mistake (i.e. that your intention was to access an instance variable), so it warns about it.
A better way to access the static variable is:
RoundCapGraph.strokeWidth = strokeWidth;
EDIT: you are setting your static variable within an instance method. This is a good indication that the compiler was right in warning you about accessing the static variable as if it was an instance variable.
You should set static variables via static methods, and set instance variables via instance methods.
When you access static member using object's instance, the instance gets replace by Class. i.e this.strokeWidth would be replace with RoundCapGraph.strokeWidth
There will be no NullPointerException due to the instance replacement.
I found a reference to this in the Java Specification: Chapter 15, Section 11: Field Access Expressions.
Example 15.11.1-2. Receiver Variable Is Irrelevant For static Field Access
The following program demonstrates that a null reference may be used to access a class (static) variable without causing an exception
public class RoundCapGraph extends View {
static private int strokeWidth = 20;
public void setStrokeWidth(int strokeWidth){
RoundCapGraph roundCapGraph = null;
roundCapGraph.strokeWidth = strokeWidth; // NullPointerException?
//warning : static member 'com.example.ud.RoundCapGraph.strokeWidth' accessed via instance reference
}
}
Correct, Static members belong to the class not to an instance.

Should immutable, final variables always be static? [duplicate]

This question already has answers here:
Should a java class' final fields always be static?
(8 answers)
Should initialized final fields that are immutable always be made static?
(1 answer)
Should a private final field be static too?
(5 answers)
Closed 4 years ago.
In java, if a variable is immutable and final then should it be a static class variable?
I ask because it seems wasteful to create a new object every time an instance of the class uses it (since it is always the same anyway).
Example:
Variables created in the method each time it is called:
public class SomeClass {
public void someMethod() {
final String someRegex = "\\d+";
final Pattern somePattern = Pattern.compile(someRegex);
...
}
}
Variables created once:
public class SomeClass {
private final static String someRegex = "\\d+";
private final static Pattern somePattern = Pattern.compile(someRegex);
public void someMethod() {
...
}
}
Is it always preferable to use the latter code?
This answer seems to indicate that it is preferable to use the latter code: How can I initialize a String array with length 0 in Java?
No definitely not.
class MyIntegerContainer{
private final int x;
public MyIntegerContainer(int x){
this.x = x;
}
}
If you made immutable, final x static, then all instances of MyIntegerContainer would share the same value of x which would not make for a very good data container.
Ultimately it depends on what you're doing with those variables.
If the variable only ever has a lifecycle inside of that specific method - that is, nothing else will ever need to see it or use those values - then declaring them inside of the method is appropriate and correct. Making it more visible than it needs to only adds to confusion for future maintainers (including yourself).
If the variable has a lifecycle outside of the class, it might make sense to declare it static. This is particularly true in the case of constants or variables that don't store any state themselves.
If it isn't a constant or it doesn't have any purpose outside of the class, then keep it non-static and private.

Access to non-static variable from static context [duplicate]

This question already has answers here:
Non-static variable cannot be referenced from a static context
(15 answers)
Closed 7 years ago.
I am trying to access a boolean variable stay from my class MontyHall but cannot because it is non-static and i am trying to access it in a static context
Here is the code:
public void updateStatistics(Door door1, Door door2, Door door3)
{
this.numGames = this.numGames + 1;
oneDoor(door1, 0);
oneDoor(door2, 1);
oneDoor(door3, 2);
if (MontyHall.stay == true){
this.numStay = this.numStay + 1;
}
else{
this.numSwitch = this.numSwitch + 1;
}
}
The variable stay is located in class MontyHall. Any help would be greatly appreciated as I am very confused how to fix this
Properties of class MontyHall:
public class MontyHall {
boolean stay;
Door A = new Door("A");
Door B = new Door("B");
Door C = new Door("C");
public MontyHall(Door a, Door b, Door c){
this.A = a;
this.B = b;
this.C = c;
}}
Your code MontyHall.stay is the part where you are trying to reference it statically (by using the class name).
A non-static field will need an instantiated object in order to reference. In this case, if this method is within MontyHall, then you can use use this.stay in order to access it, instead of MontyHall.stay. If the method you've listed above is not within the MontyHall class then you will need to create a new MontyHall object like such: MontyHall montyHall = new MontyHall();
Alternatively, you may want to make your stay variable static, in which case just add a simple static keyword to the variable declaration.
am trying to access a boolean variable stay from my class MontyHall but cannot because it is non-static and i am trying to access it in a static context
Everything is clear now. Your variable stay is an instance variable which belongs to each individual object of class MontyHall. So you shouldn't contemplate making it static just to resolve the error.
To access an instance variable, you need to create an object first. (Since it belongs to a particular object and not a class):
MontyHall hall = new MontyHall();
hall.stay; //access stay from object of MontyHall
In the rule of data protection and encapsulation, you may consider making stay variable private and use getters and setters to access it.
So if you set stay as private, you will access it like this:
hall.getStay();
Last but not least, Java do not have global variables. It is a rather common misconception to perceive class variables (static variables) as global.
You can't just access variables from non-static contexts. You will have to instantiate the class first and then access bariable from that instance. So it would go something like this:
MontyHall a = MontyHall();
a.someVariable....
Note: variable should be accessible from other classes (would recommend encapsulation depending on situation).
More info in this thread: calling non-static method in static method in Java
You want to access a variable directly from the class, without creating an instance. To do so, the variable should be declared static. In that class, you should thus define it as follows:
public class MontyHall {
public static boolean stay = true;
.....
}
Now you can access it in the way you did.
Edit
Or, as the others have mentioned as well. If stay is a variable that can change within your class, you should make an instance first.
MontyHall a = new MontyHall(....);
a.stay; // This is the stay variable from MontyHall a
MontyHall b = new MontyHall(....);
b.stay; // This stay variable could have a different value

Accessing a Super's Member of different type with the same variable name

Consider the following superclass and subclass pair, how do you access the superclass member?
class Super {
Number aNumber;
}
class Subbie extends Super {
Float aNumber;
}
You can access the super Member by super.aNumber provided it is an instance of the Subclass.
Given that the attribute does not have a visiblity modifier, it is assumed to be package private. Subbie will only be able to access Super's aNumber if they're in the same package.
If it was, you could access it like this: super.aNumber. Notice super here is a keyword that implicitly refers to the superclass, and doesn't have anything to do with the superclass being named Super.
class Super {
Number aNumber;
}
class Subbie extends Super {
Float aNumber;
public Number getNumberFromSuper() {
return super.aNumber;
}
}
I'd suggest to take a read on the excellent Java tutorials online, for instance:
Inheritance
Controlling Access to Members of a Class
You can define a field with different keywords known as Access Modifiers (check the links at the end for a detailed explanation on this topic), each one defining a scope for access/use. I'll focus this explanation on fields.
Public: Accessible by everyone. This Access Modifier is regulary used with methods and not with fields. In Java, it is encouraged the use of get and set methods to access the value of a field and change it (respectively). You can access a field this way:
AClass c = new AClass();
c.publicField = 3; //Setting a value in a field, int in this case
int sum = c.publicField + 4; //Obtaining the value of publicField to use it
Private: Definining a field as private makes it visible only to the class itself, meaning no one outside the boundaries of a class will be able to see that field. A common class in Java usually has private fields and accessors (get & set methods).
public class AClass {
public int publicField;
private String privateField = "Can't see me!";
public String getPrivateField() {
return privateField;
}
public void setPrivateField(String newValue) {
privateField = newVaule;
}
}
Getters and Setters let you control the access to your private fields, allowing you to perform any logic you desire before updating the value of that field or preparing a field in a particular before returning its value if you need it.
Protected: Only subclasses of a class and classes in the same package can access a field defined with this keyword. In your case Subbie has access to the protected fields of Super and any other class in the same package as Super has access to those fields as well.
No Access Modifier: This is your current case and the answer to your question relies strongly on the structure of your classes. If they are in the same package, then you can access Super's field from Subbie. Otherwise, if Subbie is in another package, you won't be able to access that field. This field is referenced as Package-Private.
Some related articles you might want to check:
Inheritance in Java
Controlling the Access to Members of a Class

Why am I able to call private method?

I should not be able to invoke a private method of an instantiated object. I wonder why the code below works.
public class SimpleApp2 {
/**
* #param args
*/
private int var1;
public static void main(String[] args) {
SimpleApp2 s = new SimpleApp2();
s.method1(); // interesting?!
}
private void method1() {
System.out.println("this is method1");
this.method2(); // this is ok
SimpleApp2 s2 = new SimpleApp2();
s2.method2(); // interesting?!
System.out.println(s2.var1); // interesting?!
}
private void method2() {
this.var1 = 10;
System.out.println("this is method2");
}
}
I understand that a private method is accessible from within the class. But if a method inside a class instantiate an object of that same class, shouldn't the scope rules apply to that instantiated object?
Can static method like main access the non-static member of the class, as given in this example ?
Your main method is a method of SimpleApp, so it can call SimpleApp's private methods.
Just because it's a static method doesn't prevent it behaving like a method for the purposes of public, private etc. private only prevents methods of other classes from accessing SimpleApp's methods.
Because main is also a member of SimpleApp.
See below chart
Access Modifiers
**Same Class Same Package Subclass Other packages**
**public** Y Y Y Y
**protected** Y Y Y N
**no access modifier** Y Y N N
**private** Y N N N
As your method is inside car it's accessible based on above thumb rule.
From the Java Tutorial:
private modifier—the field is accessible only within its own class
The main method is inside the same class as the private method and thus has access to it.
private means "only stuff in this class can mess around with it". It doesn't mean "only this instance can call its methods", which seems to be what you're expecting. Any code in SimpleApp can use anything in any SimpleApp. The alternative would be to break encapsulation -- how would you make a proper equals method, for example, that didn't require access to another instance's fields, without making those fields protected or even public or requiring getters for data that should only be available inside the class?
The call you issue is from within the same class where your private method resides. This is allowed. This is the way 'private' is defined in java.
In the program, we created two instances of the class by using which we called two private methods. It's a kind of interesting to see this works is that this is the way we used to call public or default methods outside its class using object reference. In this case, it's all done inside the class definition, so it's valid. The same code put outside the class will result in error.
Because the private scope limits access to the class defining the method, and your main happens to be in the same class.
private modifier—the field is accessible only within its own class.
See Access Modifiers in the Java Documentation.

Categories

Resources