class and private members [duplicate] - java

This question already has answers here:
Why is the access to a private field not forbidden?
(6 answers)
Closed 8 years ago.
class MC {
private String name;
void methodA(MC mc){
System.out.println(mc.name);
}
}
Why am I able to access name variable in methodA? I am confused here, can someone please explain?

You can access it because methodA is part of class MC. Every method in a class can access that class's private data members (in the current instance and in any other instance). Only other classes cannot. For example:
class MC {
private String name;
void methodA(MC mc){
System.out.println(mc.name);
}
}
class SomeOtherClass {
void printMC(MC mc){
System.out.println(mc.name); //compiler error here
}
}
Here is some official documentation on this topic: http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

Because private does not apply to the object, it applies to the class. If private applied to the object, then your intuition would be correct: MC.methodA would have access to this.name, but it would not have access to mc.name (where mc is some other MC object).
However, a subtle rule of visibility modifiers is that they control access for any code in that class to the members of the other objects of that same class. So all of the code in the MC class has access to the private name field of all objects of type MC. That is why MC.methodA has access to mc.name (the name of some other MC object) and not just its own name.
Edit: The relevant section of the Java Language Specification is 6.6.1 Determining Accessibility:
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.

because you have accessed it from the scope it's private to.
your private implementations and data will be private to (and accessible in) the scope (e.g. class) they have been declared in.

Related

How are private members of a class accessed via member functions of the class on memory level?

class TestMemberOuter1{
private int data=30;
class Inner{
void msg(){System.out.println("data is "+data);}
}
void display(){
Inner in=new Inner();
in.msg();
}
public static void main(String args[]){
TestMemberOuter1 obj=new TestMemberOuter1();
obj.display();
}
}
Why innerclass is able to access private members of the outerclass ?
I want to know what implementation [ at the lower level (Maybe at memory level or java implementation specific or any other not sure)] enables to achieve this kind of behaviour in java .
I dont think neither you need any memory level modifictaion or logic implementation to achieve this nor I think java will have any huge code logic at memory level to implement the same.
Memory has got nothing to do with it. Private, public and protected are just a access filters, No matter whether it is a private, public or protected all these variables will reside in a same memory which is allocated for an object.
There is no differrent memory allocation for private, public or protected variables. They are all ultimately the properties of same object.
Then how come compiler handles this ???
Its bit simpler than that.
These access filters clearly informs in what context they should be allowed to access.
Private : Only whitin the class :) Whenever compiler sees the variable which is provate being accessed any where out side the class it will flag the error Thats all.
Protected : All class within the same package :) Whenever compiler sees the variable which is Protected being accessed any where out package it will flag the error Thats all.
Public : Access to all :) No flags.
Remember accessing variables outside context results in compiler error not runtime error ?? For the same reason.
You dont need a huge logic behind it, Just keep the list of private, protected and public variables and check their usage is appropriate or not thats all.
EDIT
As per your updated question "Why innerclass is able to access private members of the outerclass ?"
Drawing the conclusion from the same analogy I explained above, private variables are allowed to be accessed anywhere within the class.
Now where is your innerclass declared? As a part of your outer class itself isn't it. So when you access the private variable of outer class inside the inner class compiler has no issue with it, because your inner class itself resides inside the outer class.
I hope I made a little sense with my answer :) Happy coding.
Currently, inner classes are compiled into distinct class files, but the compiler will insert synthetic helper methods when there is an access to a private member across nested classes. The synthetic method itself will have package-private access and perform the access to the private member within its own class.
This can be demonstrated with private methods as their execution can be traced and will show the execution of these helper methods:
public class OuterClass {
static class InnerClass {
private static void test() {
OuterClass.privateMethod();
}
}
private static void privateMethod() {
Thread.dumpStack();
}
public static void main(String[] args) {
InnerClass.test();
}
}
Running this program will print:
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1329)
at OuterClass.privateMethod(OuterClass.java:9)
at OuterClass.access$000(OuterClass.java:2)
at OuterClass$InnerClass.test(OuterClass.java:5)
at OuterClass$InnerClass.access$100(OuterClass.java:3)
at OuterClass.main(OuterClass.java:12)
These nested classes are compiled into two distinct class files OuterClass.class and OuterClass$InnerClass.class. You can see that the compiler has inserted the synthetic method access$100 into OuterClass$InnerClass which allows the main method of OuterClass to invoke the private method test of the inner class. This inner class method in turn invoked a synthetic method access$000 in the outer class which allows the invocation of privateMethod() in OuterClass.
Note that this kind of access is different to the access to private members performed with Java 8’s lambda expressions and method references. For the member access performed in that context, no helper methods are generated by the compiler and the way the JVM makes the access possible is intentionally unspecified, but we can say that for Oracle’s current JRE implementation, there will be a runtime-generated class which is indeed capable of bypassing the access restriction of private members, e.g.
import java.util.function.Consumer;
public class OuterClass {
static class InnerClass {
static final Consumer<Runnable> TEST_METHOD=InnerClass::test;
private static void test(Runnable outerMethod) {
outerMethod.run();
}
}
private static void privateMethod() {
Thread.dumpStack();
}
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
InnerClass.TEST_METHOD.accept(OuterClass::privateMethod);
}
}
As of 1.8.0_65, it prints:
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1329)
at OuterClass.privateMethod(OuterClass.java:12)
at OuterClass$InnerClass.test(OuterClass.java:8)
at OuterClass.main(OuterClass.java:16)
Not showing such helper methods, but also filtering out the runtime-generated classes. Changing privateMethod() to
private static void privateMethod() {
for(StackTraceElement e:Thread.getAllStackTraces().get(Thread.currentThread()))
System.out.println("\tat "+e);
}
reveals
at java.lang.Thread.dumpThreads(Native Method)
at java.lang.Thread.getAllStackTraces(Thread.java:1603)
at OuterClass.privateMethod(OuterClass.java:12)
at OuterClass$$Lambda$2/135721597.run(Unknown Source)
at OuterClass$InnerClass.test(OuterClass.java:8)
at OuterClass$InnerClass$$Lambda$1/471910020.accept(Unknown Source)
at OuterClass.main(OuterClass.java:16)
with the generated classes having fancy names like OuterClass$InnerClass$$Lambda$1/471910020 and OuterClass$$Lambda$2/135721597 which are accessing the private members. Note that the generation of these classes has been triggered by the classes which have the right to access these private members, which has been checked before allowing to create such function objects.

Java - Protected field not accessible from the subclass? [duplicate]

This question already has answers here:
Understanding Java's protected modifier
(6 answers)
Closed 7 years ago.
I am in process of learning the Java access modifiers. For that, I have created a class Machine:
package udemy.beginner.interfaces;
public class Machine {
public String name;
private int id;
protected String description;
String serialNumber;
public static int count;
public Machine(){
name = "Machine";
count++;
description = "Hello";
}
}
Then, in another package, I have created a class Robot as a subclass of a car Machine:
package udemy.beginner.inheritance;
import udemy.beginner.interfaces.Machine;
public class Robot extends Machine {
public Robot(){
Machine mach1 = new Machine();
String name = mach1.name;
//here I am getting error "The field Machine.description is not visible"
String description = mach1.description;
}
}
I am getting an error when trying to access the field description in the class Robot. From my understand of how protected access modifier works, it should be OK though, but maybe I messed up something. Any thoughts?
EDIT: I have tried to move Robot class to the same package as Machine class is in and now it works, without a need to use this. If someone can explain me this. According to the answers below, it should not work as well ...
You can't access a protected superclass field in a different instance of the class.
There's a good reason: you don't know whether it has the same subclass as yourself, or a completely different subclass. If it were allowed to access the protected field, you would be allowed to access the internals of entirely unrelated classes.
If you are sure that the object is of the same subclass as the class that wants to access the superclass field, you can cast the object; when you that, you can access the protected field.
The rules are described in the Java Language Specification section 6.6.2
6.6.2. Details on protected Access
A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is
responsible for the implementation of that object.
6.6.2.1. Access to a protected Member
Let C be the class in which a protected member is declared. Access is
permitted only within the body of a subclass S of C.
In addition, if Id denotes an instance field or instance method, then:
If the access is by a qualified name Q.Id, where Q is an
ExpressionName, then the access is permitted if and only if the type
of the expression Q is S or a subclass of S. [This is the relevant section]
protected variables are accessible outside class, but only through inheritance. So, if you change that statement to this:
public Robot(){
Machine mach1 = new Machine();
String name = mach1.name;
// This will work (access on `this` reference)
String description = this.description;
}
Actually protected modifier means that, the field is visible to be inherited by the subclasses, and it can be used only there, using this reference.

In what context are statements in Java interface definitions executed?

I'm looking at the definition of org.apache.maven.plugin.Mojo:
public interface Mojo
{
String ROLE = Mojo.class.getName();
[...]
}
I'm lost. To my knowledge, Java interfaces are a set of method signatures. So what's this line which looks like a statement doing here? What are the semantics? For example:
When does that line get "executed"?
In the context in which that line runs, what does Mojo refer to? What is its type?
In the context in which that line runs, what does Mojo.class refer to? I assume its type is java.lang.Class?
In what context can I read that ROLE variable? What is the syntax for doing so? What will the variable contain?
Can I write to that ROLE variable?
All the fields of an interface are implicitely public, static and final. So this is the same as writing
public static final String ROLE = Mojo.class.getName();
It defines a constant, that all the users of the interface can use, as any other constant: Mojo.ROLE. This line is executed when the Mojo interface is initialized by the ClassLoader. Mojo.class is the Mojo class, indeed of type java.lang.Class<Mojo>. Since the package of the class is org.apache.maven.plugin, the value of the constant will be "org.apache.maven.plugin.Mojo".
Look here for the relevant section of the Java language specification.
the variable get defined when class loader loads the class.
interface variables are static final and can be accessed statically by any class that implements the interface.
public class MyClass implements Mojo{
.
.
.
}
access:
public void someMethod(){
System.out.println(MyClass.ROLE)
}
All fields in an interface are implicitly static and final. That answers some of your questions:
The line gets executed during the static execution. That is possibly during compilation, possibly at the launching of the program and possibly when the class loader loads that class. It's a complicated business, but it's the same as all other static fields.
Mojo refers to the interface itself, statically. It is a type itself, so it has no type.
Mojo.class refers to the java.lang.Class of Mojo.
You can read the ROLE variable in any class that implements Mojo. You can only read it statically, like Mojo.ROLE.
No, the field is final, so you can't write to it. It is intended for constants only.
When does that line get "executed"?
Any member of an Interface is static and final by default, so String ROLE (which can effectivly be seen as
public static final String ROLE
will be initialized, as every static member, when the ClassLoader loads the class (by the first time, the class is referenced).
JLS - Loading of Classes and Interfaces
In the context in which that line runs, what does Mojo refer to? What is its type?
In the context in which that line runs, what does Mojo.class refer to? I assume its type is java.lang.Class?
Mojo is of the type java.lang.Class<Mojo>
In what context can I read that ROLE variable? What is the syntax for doing so? What will the variable contain?
As it is implicit public static final you can access it from everywhere by using Mojo.ROLE or through the implementing classes by ClassName.ROLE. As Class#getName() says in the java doc, it will contain the full qualified name of the object:
org.apache.maven.plugin.Mojo
Can I write to that ROLE variable?
No, you cannot, because it is implicit final
JLS - Interfaces

Scope of protected members

Iam preparing for SCJP , also i came to know that protected members scope is within the package as well as in other package with some conditions like possible only with inheritance.
For example :
i have three classes as Parentclass Childclass Friendclass
package x.parent;
class Parentclass{
protected int x=10;
...............
}
package x.child;
class Childlass extends Parentclass{
super.x=20;
...............
}
package x.child;
import x.parent.Parentclass;
class Friendclass{
Parentclass pc = new Parentclass();
pc.x=30;
...............
}
Whats the reason behind that, in Friendclass the member x will not accept to assign a value to that, behaves as private member not in case of Childclass.
There are four access modifiers
private - just this class
no modifier - just this class or this package (NOT subclass)
protected - just this class, this package, or subclass
public - everyone and their cousin
Since it uses the default modifier, it has access if one of the following is true:
Is part of the class itself (Nope!)
Is part of the package of the class itself (Nope!)
So it fails the criteria, and so you don't get access.
You can't even access Parentclass.x in Childclass because x has default visibility (not protected). See http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
edit:
x.child.Friendclass is not in the same package as x.parent.Parentclass.
x.child.Friendclass does not inherit from x.parent.Parentclass.
as TotalFrickinRockstarFromMars's summary states and the Java access control docs also state, this means that Friendclass is not allowed to access the field x.

Private variables in a class can be accessed from main in Java?

I've recently started learning Java using JDK1.6. If this is a silly question, please excuse me.
If private variables can be directly accessed by objects in main() how are they 'private'?
public class Account1
{
private int accountNum;
private String name;
Account1() {
accountNum = 1101;
name = "Scott";
}
public void showData() {
System.out.println("Account Number: " + accountNum +
"\nName: " + name);
}
public static void main(String[] args) {
Account1 myA1 = new Account1();
myA1.showData();
System.out.println(myA1.accountNum); //Works! What about "Private"?!
}
}
Which gives the output:
Account Number: 1101
Name: Scott
1101
Your main is in the Account1 class, so it's still in the same scope.
Private variables can be accessed from any code belonging to the same type. If your main method was in a separate class then it wouldn't be able to access them (without using reflection).
The "main" method of a given class is part of that class. Methods that are part of a class have access to private members of that class. That makes sense to me. Doesn't necessarily mean you should use it, of course.
One way to think about it is to think about one class's knowledge of another class's internal workings. My Person class shouldn't know what happens inside my Order class; it just calls public methods on it. But anything inside Person will of course know about the internal structure of Person -- even a different instance of Person.
This is because the main() function is a member of the class. It has access to all members of the class.
In real world code, the main function is usually situated in a "harness" class that actually bootstraps the rest of the code. This harness class is usually very lightweight and instantiates other classes that do the real work.
They are private in that they can only be accessed by that class. This means they are accessible from static methods of that class (such as main) and also from instance methods (such as showData).
One instance of the class can also access private members of another instance of the class.
If you had a separate class, say, Account2, it would not be able to access provate members of Account1.

Categories

Resources