Breaking encapsulation and information hiding in Java - java

Consider the following snippet.
package breakoop;
public class BreakOOP {
public static class A{
private int a;
}
public static class B extends A{
public int f(){
return super.a;
}
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.f());
}
}
The example only compiles if A and B are encapsulated within the BreakOOP class.
This seems to go against some of the fundamental concepts of OOP. Can someone explain why this compiles? What is the reasoning behind it?

Check this: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html. It says it increases encapsulation by allowing the static class to access private members of the top level class (sometimes you may need to do that). And a is private member of class A, which is in the scope of BreakOOP, which in turn makes it accessible inside class B.

The Java Language Specification states:
A private class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Since classes A and B are defined within the body of BreakOOP that rule applies and B can see private members of A.
As for the OOP concepts: since A and B are static inner classes they don't have the special life-cycle relation with BreakOOP that true inner classes have (i.e. you don't need an instance of BreakOOP to create a new instance of A or B but they still have a somewhat special relation in that they have access to private members. If they should not have that kind of relationship then they shouldn't be inner classes but true top level classes.

Related

Why can't a local class that extends an inner class access the inner class enclosing instance?

(I keep re-reading that question title and thinking about how ridiculous it must look, but I assure you that is the best description of the problem, and I have an actual application where this is the best structure. I swear I'm not crazy.)
Consider the following. Each block is a separate file:
package myPackage;
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
}
}
package myPackage;
import myPackage.A.B;
public class Main {
public static void main(String[] args) {
class C extends B {
public C(A enclosingInstance) {
enclosingInstance.super();
}
public void show() {
System.out.println(A.this.i);
}
}
A myA = new A(2);
C myC = new C(myA);
myC.show();
}
}
Note that the enclosingInstance business is to solve a problem involving intermediate constructor invocations. See "Why can't outer classes extend inner classes?".
I would expect the output to be "2". But instead, I have a compile error on System.out.println(A.this.i);:
No enclosing instance of the type A is accessible in scope
I think the programmatic concept I'm trying to solve is sound: Create a new type of B inside main to give to A that uses things from A that types of B can access.
So what am I doing wrong, or why isn't this possible in java?
EDIT/UPDATE: Note that the same error appears when the code in main is moved to a non-static method. That is to say, I tried moving everything inside of static void main to a new, non-static method of class Main called go(). Then I changed static void main to the single line new Main().go();. The error is in the same spot. So it doesn't seem to be an issue of class C being defined in a static context.
You want A.this to refer to the enclosing instance of the B instance. But why should it? That's not what the syntax means. A.this would mean the enclosing A instance of the C instance, and this does not make sense because C is not an inner class of A.
To make this clearer, here is an example where C is an inner class of A.
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
void foo() {
System.out.println(A.this.i);
}
}
public class C extends B {
C(A a) {
a.super();
}
void bar() {
System.out.println(A.this.i);
}
}
public static void main(String[] args) {
A a1 = new A(1);
A a2 = new A(2);
C c = a1.new C(a2);
c.foo();
c.bar();
}
}
Here C extends B, and both C and B are inner classes of A. Therefore any C has an enclosing A instance, and it also has an enclosing A instance when considered as a B, and these enclosing instances are different (as proved by the fact that foo and bar print different numbers).
So, A.this could not possibly mean what you want it to mean, because it already means something else. I guess the reason why the language designers didn't come up with other syntax to mean the enclosing instance of a super class, is because such syntax would be very complicated, with little pay-off (simple workarounds already exist).
This is absurd code that you should never write for production.
It is, in part, explained in the documentation for Explicit Constructor Invocations
Qualified superclass constructor invocations begin with a Primary
expression or an ExpressionName. They allow a subclass constructor to
explicitly specify the newly created object's immediately enclosing
instance with respect to the direct superclass (§8.1.3). This may be
necessary when the superclass is an inner class.
All this to say that C is a local class (which is an inner class, which is kind of nonsense because if you declare it in a static method there is no enclosing instance) that is a subclass of B but not a nested class of A. As such, there is no enclosing instance. An instance of C does not have an enclosing instance. (Though it would if you declared it in an instance method, but that would be an instance of Main.)
The newly created object's immediately enclosing instance (from JLS) is specified indirectly through a constructor parameter.
You'd have to store it yourself
private A enclosingInstance;
public C(A enclosingInstance) throws CloneNotSupportedException {
enclosingInstance.super();
this.enclosingInstance = enclosingInstance;
}
and since A#i is public, you can access it normally
public void show() {
System.out.println(enclosingInstance.i);
}
With the provided information, I would do this :
public class B {
protected A getOuterInstance() {
return A.this;
}
}
and just let C inherit and use this method. I know you dislike this method but this is the simplest answer I can see. With more information, I would probably propose a design which would try not involving any inner class as this is not a normal use case for inner classes.

abstract private inner class

I am preparing for an Oracle examination and answered incorrectly to the following question:
the combination abstract private is legal for inner classes
As it turns the answer is true, I answered false, as I could not find any use cases for having an abstract private inner class, that cannot be overridden from subclasses. Can someone explain, why/for what do we have that in the language?
The Java language specification defines the meaning of private members as follows:
Otherwise, the member or constructor is declared private, and 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.
That is, a private inner class is accessible (and may be subclassed) from any code residing in the same source file. For instance, you could do:
public class C {
private abstract class A {
abstract void foo();
}
void bar() {
new A() {
#Override void foo() {
// do something
}
}
}
}
It is interesting to note that a method declared private can not be overriden, but methods in private classes can be.
the combination abstract private is legal for inner classes
Its a bit confusing but the rule is that an inner class can't have an abstract private method.
if exam is saying the contrary then its wrong.
UPDATE: if what you mean is in class declaration, then answer is true, check this valid piece of code...
public class MyOuter {
abstract private class MyInner {
//the combination abstract private is legal for inner classes: TRUE
}
}
To know why or when use it, check the suggested link, there is a good explanation about this...

Why static final variables are accepted in inner classees?

I know that it's possible to do the following:
public class Indeed{
private class inner {
static final int try1 = 10;
}
}
Why? what's the point of allowing such a declaration?
Moreover it's still possible do the same thing in a local class:
public void doThing() {
class LocalClass {
static final int try1 = 10;
}
}
What's the use of a static final in those bits of code?
I am pretty sure I'll never use them, however I need to understand why they are used as I have an OCPJP7 exam to do.
Thanks in advance.
The purpose of a static variable is to be shared by all instances of the class. In both examples, you can have several instances of your private class / local class, so as specified they will share static variables among instances. What would be pointless is if you could only instantiate your class once.
JLS 8.1.3. : Inner Classes and Enclosing Instances
Inner classes may not declare static members, unless they are constant
variables (§4.12.4), or a compile-time error occurs.
The way I see it in the specs, is not having to answer the following dilemma:
static variables of an inner class are shared amongst all instances of the same outer class instance (but they can have different values from an outer class instance to another)
static variables of an inner class are shared amongst all existing instances in the VM, whatever their outer class instances.
Fortunately, when you declare it final, you know it will be the same for every instance, so you don't have to worry about this problem. That's why it is allowed.
For the question "why do static fields of inner classes have to be final":
This restriction is stated in the JLS as
Inner classes may not declare static members, unless they are constant
variables (§4.12.4), or a compile-time error occurs.
But this doesn't tell us why. Let's think about how we use inner classes. Imagine I write (try to) this.
public class A{
private class B{
static x;
}
public void updateX(int y){
B.x=y;
}
public void printX(){
System.out.println(x);
}
}
What happens when I do this
A one = new A();
A two = new A();
one.doStuff(1);
two.doStuff(2);
one.printX();
two.printX();
What should be printed? 1 then 2 or 2 twice? x is static so it should only exist in one place (in the Klass object of B) but as B is an inner class it should be specific to that instance of A. If we allowed static non final fields we would need to create an instance-specific Klass object per instance of the outer class. Which we don't want to have to do!
Static final fields are therefore allowed as they can live in the Klass object of B happily, and be shared across all instances of the outer class, because they can never change (being final).

static variables in inheritance

public class A
{
public static int i;
}
public class B extends A
{
public static void main(String[] args)
{
System.out.println("print i=" + B.i); // referred to A.i
}
}
My question here is how B.i is referred to the A.i?
If the static variable i is inherited why java allows to define another variable i in B class also?
A public or protected member of A is visible in all subclasses of A.
If the static variable i is inherited why java allows to define another variable i in B class also?
It's hard to speculate as to why. One possible reason is that this allows one to add members to a base class without breaking any derived classes that already happen to have a member with the same name.
Note that, if you define another i in B, it will shadow A.i, making it difficult to access the latter. I've seen people expecting this to behave polymorphically, but it doesn't (your case is slightly different anyway, since A.i is static).
i here is a static variable.A static variable,in layman terms,means a single copy being accessed by all classes.So,since your class B extends A,B has an access to the static variable of A.
If you define the variable locally,then the local value of the variable hides the parent class value.
there are 2 different things, scope and visibility. you can not redefine a variable in same scope twice (though you can redefine them in nested scopes).
But in case of inheritance, the subclass is out of scope of superclass, but yet has the visibility to that variable because of inheritance. So sub class allows you to define variable i again, though it will hide super class's variable. you wont be able to see its value. (unless used any getter from superclass)
Java allows you to change the specific variable value for the extended class.
This is because, static variables are shared between all objects of the same class.
It is a variable which belongs to the class and not to object(instance).
So, when extending the static variables of the parent class are not actually part of the extended class BUT are accessible (as long as they were not private).
Additionally, this can be used to do things such as:
using different STATIC CONSTANT for extended classes.
A use for this is to identify classes based on a STATIC integer as apposed to utilizing instanceof. This can be further combined with a switch to change behavior based on an objects type.
So, in the most basic example imagine we want to create a variable represent TYPE.
class A
{
public static final int NODE_TYPE = NODE_PERSON;
public static final int NODE_PERSON = 0;
public static final int NODE_CAR = 1;
}
class B extends Class A
{
public static int NODE_TYPE = NODE_CAR;
}
This has been used in many frameworks including Eclipse Abstract Syntax Trees:
http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fcore%2Fdom%2FASTNode.html
You will see a list of STATIC INTEGERS which represent different Node Types.

Java Multilevel Inheritance - Protected Instance Variable in Level 1 Class

I have an question which comes under multilevel inheritance in Java. All Three Classes are in Same package
I have class A :
public class A {
protected int x;
}
public class B extends A {
public void doSomething {
// x is visible.agreed, as it is a direct subclass of A
}
}
public class C extends B {
public void doSomething {
// x is still visible, how come? I mean it is at the 2nd level
// I am confused why?
}
}
does it like have any significance? or it is behavior which we have to take it by default?
variable/methods marked with protected modifier are visible to all the classes in the same pacakage and only to subclasses in different packages.
below are the example cases.
package a;
class A{
protected int x;
}
class B extends A{
//x can be accessed from this class
}
class C extends B {
//x can be accessed from this class
}
class D{
//x can be accesed this class but you will have to create A's instance
}
package B
class One {
//cannot access x from this class
}
class Two extends A {
//can access x from this class
}
The access level modifiers in Java are:
public - visible to all code
protected - visible to all code in the same package and to subclasses regardless of package
nothing (default) - visible to all code in the same package
private - visible only to code in the same class (including nested classes)
See, for instance, the Java tutorial Controlling Access to Members of a Class or (for lots of technical details) section 6.6 of the Java Language Specification.
Definition of the keyword
Protected
The protected modifier specifies that the member can only be accessed
within its own package (as with package-private) and, in addition, by
a subclass of its class in another package.
I suggest you read this.
The Java protected keyword works its way down to all subclasses (and members of the package). If there was a protected member in Object, any object could access it. By contrast, private is only visible to the local class (and inner classes), and public is accessible by all.
Have a look at this glossary, which shows in-depth how protected members and methods are inherited, and the Java documentation on inheritance.
You cannot restrict access to members in subclasses. This rule applies to methods (you can't override public method and make it private) but you can see analogy here. If the field is protected, it will be protected in every subclass, no matter how deep. Of course you can't override fields in Java, but just to give you an overview.
Please refer this: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
So if your class C shares the package with A and B, its accessible.
Inheritance is transitive: if class B inherits from class A;
and class C inherits from class B; then C is also a
subclass / child class / descendant of class A.

Categories