The private access modifier is used so that we can use the respective member only within the class. But using inner classes, we can define a method to access the private members of the outer class. Here is the code for that:
import java.util.*;
import java.lang.*;
import java.io.*;
class Outer {
private int x = 1;
Inner getInner() {
Inner inner = new Inner();
return inner;
}
class Inner {
int getX() {
return x;
}
}
}
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Outer outer = new Outer();
Outer.Inner inner = outer.getInner();
System.out.println("Private x: "+inner.getX());
}
}
Doesn't it go against the concept of Encapsulation?
The private access modifier is used so that we can use the respective
member only within the class.
Since the inner class is part of the class, this still holds. The access to private data is confined within, so encapsulation is preserved.
Besides, since you're able to modify the source file of the class, it means you have access to all its internals anyway.
The "Inner" class is a part of the "capsule" - the Outer class. So it is absolutely ok, that it can access private variables of the Outer class. The point of Encapsulation is to hide parts of implementation from the outside and the "Inner" class is not outside, it is inside the class.
Related
Is there any way to access the methods of local inner classes in Java. Following code is the sample code that I tried before. According to that what is the mechanism to access the mInner() method?
class Outer{
int a=100;
Object mOuter(){
class Inner{
void mInner(){
int y=200;
System.out.println("mInner..");
System.out.println("y : "+y);
}
}
Inner iob=new Inner();
return iob;
}
}
class Demo{
public static void main(String args[]){
Outer t=new Outer();
Object ob=t.mOuter();
ob.mInner(); // ?need a solution..
}
}
As ILikeTau's comment says, you can't access a class that you define in a method. You could define it outside the method, but another possibility is to define an interface (or abstract class). Then the code would still be inside your method, and could access final variables and parameters defined in the method (which you couldn't do if you moved the whole class outside). Something like:
class Outer {
int a = 100;
public interface AnInterface {
void mInner(); // automatically "public"
}
AnInterface mOuter() { // note that the return type is no longer Object
class Inner implements AnInterface {
#Override
public void mInner() { // must be public
int y = 200;
System.out.println("mInner..");
System.out.println("y : " + y);
}
}
Inner iob = new Inner();
return iob;
}
}
class Demo {
public static void main(String[] args) { // the preferred syntax
Outer t = new Outer();
Outer.AnInterface ob = t.mOuter();
ob.mInner();
}
}
Note: not tested
Note that the return type, and the type of ob, have been changed from Object. That's because in Java, if you declare something to be an Object, you can only access the methods defined for Object. The compiler has to know, at compile time (not at run time) that your object ob has an mInner method, and it can't tell that if the only thing it knows is that it's an Object. By changing it to AnInterface, the compiler now knows that it has an mInner() method.
The scoping rules of a local class are pretty much the same as the scoping rules of a variable, that is, it is confined to the enclosing block.
The same way you cannot access variable iob from main, you cannot access local class Inner from main.
Outside the enclosing block, there's no difference between a local class and an anonymous class. Neither can be accessed. The difference is that within the enclosing block, the local class can be accessed by name, especially useful if you need to access it repeatedly, e.g. to create multiple instances.
The only way to interact with a local/anonymous class outside the enclosing block, is through any superclass or interface implemented by the class in question.
To access the inner class create an object of inner class..
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
from your example
outer t=new outer();
outer.inner inner1=t.new inner();
Hope this helps you...
//below class is the example where in subclass extends the innerclass and from the subclass i am trying to access the methods of outer class i.e encapsulating class of inner class.
package innerClass;
public class outterclass {
private int outer=24;
protected int get_outer(){
return outer;
}
protected static class innerclass{
private int outer=25;
protected int get_outer(){
return outer;
}
}
}
package innerClass;
public class subclass_B extends outterclass.innerclass {
void parent_class_info_fetch(){
System.out.println(get_outer());
//i want to access the outer class get_outer method and how do i achieve that?
}
public static void main(String[] args) {
InheritanceStaticInnerClass_B isb=new InheritanceStaticInnerClass_B();
isb.parent_class_info_fetch();
}
}
Your innerclass is not an inner class. It is a static nested class and bears no special relationship to its enclosing class. You cannot reach an instance of the enclosing class because no such instance is available to innerclass or its subclasses.
If innerclass was indeed inner, then you would have to instantiate it with an enclosing instance:
outterclass outer = new outerclass();
subclass_B b = outer.new subclass_B();
Then, in parent_class_info_fetch() you could write
outterclass.this.get_outer()
to reach that method.
Of course, there would be several layers of bad practices in such code, so consider this just an academic execrise.
You should also learn about the basic naming conventions in Java.
The class outterclass.innerclass is a static class field, which means you don't necessarily have an enclosing instance of outterclass. On the other hand, the method get_outer of outterclass is an instance method, so you'll need the enclosing instance to call it.
With the class hierarchy you have, you'd have to make get_outer static (which requires making outer static as well).
I have an inner class in my Java class.
When I run find bugs, it recommends(warns) to make it as static.
What's the point of this warning? What's the advantage of making a inner class as static?
If the nested class does not access any of the variables of the enclosing class, it can be made static. The advantage of this is that you do not need an enclosing instance of the outer class to use the nested class.
An inner class, by default, has an implicit reference to an object of the outer class. If you instantiate an object of this from the code of the outer class, this is all done for you. If you do otherwise you need to provide the object yourself.
A static inner class does not have this.
That means it can be instantiated outside the scope of an outer class object. It also means that if you 'export' an instance of the inner class, it will not prevent the current object to be collected.
As a basic rule, if the inner class has no reason to access the outer one, you should make it static by default.
A static inner class is a semantically simpler thing. It's just like a top-level class except you have more options for visibility (e.g. you can make it private).
An important reason to avoid non-static inner classes is that they are more complex. There is the hidden reference to the outer class (maybe even more than one). And a simple name in a method of the inner class may now be one of three things: a local, a field, or a field of an outer class.
An artifact of that complexity is that the hidden reference to the outer class can lead to memory leaks. Say the inner class is a listener and could be a static inner class. As long as the listener is registered, it holds a reference to the instance of the outer class, which may in turn hold on to large amounts of memory. Making the listener static may allow the outer instance to be garbage collected.
A Non-static inner class has an implicit reference to outer class. If you make the class as static, you could save some memory and code.
Benefits of static inner classes:
Instantiation of static inner class does not rely on external class guidance, and the memory overhead of instantiation.
Static inner class does not hold external class guidance, does not affect the collection of external class, to avoid the extension of the external class in memory survival time leading to memory leakage.
We already have good answers, here are my 5 cents:
Both static and non-static inner classes are used when we need to separate logical functionalities yet using the methods and variables of the outer class. Both of the inner classes have access to the private variables of the outer class.
Advantages of static inner class:
1) static classes can access the static variables from outer class
2) static classes can be treated like an independent class
Non-static inner class:
1) cannot use static members of the outer class
2) cannot be treated like an independent class
public class NestedClassDemo {
private int a = 100;
int b = 200;
private static int c = 500;
public NestedClassDemo() {
TestInnerStatic teststat = new TestInnerStatic();
System.out.println("const of NestedClassDemo, a is:"+a+", b is:"+b+".."+teststat.teststat_a);
}
public String getTask1(){
return new TestInnerClass().getTask1();
}
public String getTask2(){
return getTask1();
}
class TestInnerClass{
int test_a = 10;
TestInnerClass() {
System.out.println("const of testinner private member of outerlcass"+a+"..."+c);
}
String getTask1(){
return "task1 from inner:"+test_a+","+a;
}
}
static class TestInnerStatic{
int teststat_a = 20;
public TestInnerStatic() {
System.out.println("const of testinnerstat:"+teststat_a+" member of outer:"+c);
}
String getTask1stat(){
return "task1 from inner stat:"+teststat_a+","+c;
}
}
public static void main(String[] args){
TestInnerStatic teststat = new TestInnerStatic();
System.out.println(teststat.teststat_a);
NestedClassDemo nestdemo = new NestedClassDemo();
System.out.println(nestdemo.getTask1()+"...."+nestdemo.getTask2());
}
}
Accessing the static inner and non-static inner class from outside:
public class TestClass {
public static void main(String[] args){
NestedClassDemo.TestInnerClass a = new NestedClassDemo().new TestInnerClass();
NestedClassDemo.TestInnerStatic b = new NestedClassDemo.TestInnerStatic();
}
}
The official java doc for static inner class can be found at https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
If a class is private then must the constructor be private as well?
No, there is no such restriction. See JLS ยง8.8.3. Constructor Modifiers.
It's worth pointing out that only a nested class can be declared private. The JLS permits the constructors for such a class to use any valid access modifiers.
If you mean nested class, the answer is no. Making the inner class private makes it only usable within the outer class.
Edit: It appears that outer classes have full access to the innards of the inner classes regardless of their access modifiers. This invalidates my above reasoning, but regardless, there is no such restriction. Curiously though, now it appears that if the inner class is private, its constructor is essentially private, regardless of its access modifier, since noone else can call it.
No it hasn't. On the contrary, if you create an instance of the inner class using a private constructor (which is default for a private class) from the outer class Java will create an additional class to prevent access violation and keep JVM happy
If you compile this class
class Test {
private class Test2 {
Test2() {
}
}
Test() {
new Test2();
}
}
javac will create Test.class, Test#Test2.class
and if you compile this class
class Test {
private class Test2 {
}
Test() {
new Test2();
}
}
javac will create Test.class, Test#Test2.class, Test$1.class
No it is not fix, you can set it private/public/any you want.
But in some case I prefer to make constructor private, when you don't want to allow other classes to create object of this class. then in that case you can do something like this, by setting constructor private.
private class TestClass{
private TestClass testClass=null;
private TestClass(){
//can not accessed from out side
// so out side classes can not create object
// of this class
}
public TestClass getInstance(){
//do some code here to
// or if you want to allow only one instance of this class to be created and used
// then you can do this
if(testClass==null)
testClass = new TestClass();
return testClass;
}
}
Btw it depends on your requirement.
It does not have to be private. But it can. Example:
public class Outer {
// inner class with private constructor
private class Inner {
private Inner() {
super();
}
}
// this works even though the constructor is private.
// We are in the scope of an instance of Outer
Inner i = new Inner();
// let's try from a static method
// we are not in the scope of an instance of Outer
public static void main(String[] args) {
// this will NOT work, "need to have Inner instance"
Inner inner1 = new Inner();
// this WILL work
Inner inner2 = new Outer().new Inner();
}
}
// scope of another class
class Other {
// this will NOT work, "Inner not known"
Inner inner = new Outer().new Inner();
}
It doesn't make a difference if you use private or public constructor on private inner classes. The reason is that the inner class instance is part of the outer class instance. This picture says it all:
Note that we are talking about an inner class. If the nested class was static, the official terminology is static nested class, which is different from an inner class. A public static nested class would be accessible without outer class instance just by calling new Outer.Inner(). See here for more information about inner- and nested classes. http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
The inner class is the class defined inside a class, and the inner class can be declared as public, private, protected. If the inner class defined as private and protected, can outer class access the members of inner class? and can inner class access members of outer class?
If the inner class defined as private
and protected, can outer class access
the members of inner class?
Yes. These qualifiers will only affect the visibility of the inner class in classes that derive from the outer class.
Can inner class access members of
outer class?
Yes, including the ones declared private, just as any instance method can.
In general, you can (access private fields on inner classes and vice-versa). The following code compiles under Eclipse:
public class Outer {
private int x;
public void f() {
Inner inner = new Inner();
inner.g();
inner.y = 5;
}
private class Inner {
private int y;
public void g() { x = 5; }
}
}
That said, you can configure your IDE/compiler to treat accesses to such fields as errors (in Eclipse this setting is called "Access to non-accessible member of an enclosing type", under Preferences -> Java -> Compiler -> Error/Warnings -> Code Style)
Explanation is in context of regular inner class[Regular inner classes cannot have static members declared inside them]
You can access any field of outer class from inner class directly.
class Outer {
private static int x = 0;
class Inner {
void print() {
System.out.println(x); // x can be directly accessed
}
}
public static void main(String[] args) {
new Outer().new Inner().print();
}
}
Even Outer class can access any field of Inner class but through object of inner class.
class Outer {
private class Inner {
private int x = 10;
}
void print() {
Inner inner = new Inner();
System.out.println(inner.x);
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.print();
}
}
"A nested class is a class defined
within another class. A nested class
should exist only to serve its
enclosing class. If a nested class
would be useful in some other context,
then it should be a top-level class.
There are four kinds of nested
classes: static member classes,
nonstatic member classes, anonymous
classes, and local classes. All but
the first kind are known as inner
classes."
(Joshua Bloch, from the book Effective Java.)
As for your questions: it is very easy to test by yourself. But the answer is yes (even for private members), as long as you are not trying to access a non-static member (other than from a reference) from a static context, or trying to access a member which is in an inaccessible scope.
That is, very much as one would expect =).
Yes! You can access both an inner class member from outer class, and vice-versa(irrespective of the access modifier).
However, for a static nested class you cannot access its field just by the field name, and you need to access it like
InnerClass.staticInnerField
though you can access the static fields of the outer class from the inner class directly by the fields names.