I have a class which has another static inner class:
class A {
private List<String> list;
public static class B {
// I want to update list here without making list as static
// I don't have an object for outer class
}
}
You generally use static classes when you don't need access to the instance variables. If you need to access the instance variables make the class non-static.
As you can see from other answers that you will need a non-static inner class to do that.
If you really cannot make your inner class non-static then you can add required getter and setter method in outer class and access them by creating an instance of outer class from inside inner static class:
public class A {
private List<String> list = new ArrayList<>();
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public static class B {
// i want to update list here without making list as static
void updList() {
A a = new A();
a.setList(someOtherList);
System.out.println(a.getList());
}
}
}
No, you'll need a non-static inner class to do that.
From the JLS §8.5.1:
The static keyword may modify the declaration of a member type C within the body of a non-inner class or interface T. Its effect is to declare that C is not an inner class. Just as a static method of T has no current instance of T in its body, C also has no current instance of T, nor does it have any lexically enclosing instances.
It is a compile-time error if a static class contains a usage of a non-static member of an enclosing class.
In your code, list is an instance variable of class A and B is nested static class. The rules of accessing static and not static member don't change for nested static class.
The variable list is instance variable so a can't be accessed from static context.
To enable this, you need to change static nester class to inner class.
class A {
private List<String> list = new ArrayList<String>();
public class B {
public void someMethod(){
list.add("abc");
}
}
}
private List<String> list;
Here list is an instance variable while the inner class is static which means that class B is the same across different class A instances; one cannot access it. And, that too for a very good and obvious reason.
One solution that you can use is pass reference of member list to the constructor of class B with a weakReference to avoid memory leak.
Something like this:
class A {
private List<String> list;
public static class B {
WeakReference<List<String>> innerList;
//constructor
B(WeakReference<List<String>> innerList){
this.innerList = innerList;
}
}
Related
I was reading Effective Java 2 - Item 22 and it says in the title:
"Favor static member classes over non-static"
but at the end of the chapter
Implementations of the collection interfaces, such as Set and List,
typically use nonstatic member classes to implement their iterators:
// Typical use of a nonstatic member class
public class MySet<E> extends AbstractSet<E> {
... // Bulk of the class omitted
public Iterator<E> iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator<E> {
...
}
}
I made a test program to see if there is any difference between them and here it is.
public class JavaApplication7 {
public static void main(String[] args) {
// TODO code application logic here
JavaApplication7 t = new JavaApplication7();
Inner nonStaticObject = t.getAClass();
Sinner staticObject = new JavaApplication7.Sinner();
nonStaticObject.testIt();
staticObject.testIt();
}
public Inner getAClass(){
return new Inner();
}
static class Sinner{
public void testIt(){
System.out.println("I am inner");
}
}
class Inner{
public void testIt(){
System.out.println("I am inner");
}
}
}
The output is
I am inner
I am inner
So, they did the same job.
I wonder Why non-static class is used in this example?
An iterator usually needs to refer to the collection used to create it in the first place. You can do that with a static nested class which is explicitly provided with a reference to the collection - or you can just use an inner class, which has that reference implicitly.
Basically, if every instance of the nested class needs an instance of the enclosing class to operate (and that instance doesn't change), then you might as well make it an inner class. Otherwise, make it a static nested class.
the difference is that non-static inner class have an implicit reference to the containing class.
public class JavaApplication7 {
//You can access this attribute in non-static inner class
private String anyAttribute;
public Inner getAClass(){
return new Inner();
}
static class Sinner{
public void testIt(){
//Here, you cannot access JavaApplication7.this
}
}
class Inner{
public void testIt(){
//Here, you can access JavaApplication7.this
//You can also access *anyAttribute* or call non-static method getAClass()
}
}
}
The difference between static and non-static nested classes is that the non-static ones are implicitly associated with an instance of the outer class, which they can refer to as OuterClassName.this. This reference is useful when implementing iterators, as they need access to the members of the collection they are related to. You could achieve the same thing by using a static nested class which is explicitly handed a reference to the outer class.
there is no such thing as a static inner class, It is static nested class. "Each instance of a nonstatic [nested] class is implicitly associated with an enclosing instance of its containing class... It is possible to invoke methods on the enclosing instance."
A static nested class does not have access to the enclosing instance.
reference: this so thread
In the case of creating instance, the instance of non s
static inner class is created with the reference of
object of outer class in which it is defined……this
means it have inclosing instance …….
But the instance of static inner class
is created with the reference of Outer class, not with
the reference of object of outer class…..this means it
have not inclosing instance…
For example……
class A
{
class B
{
// static int x; not allowed here…..
}
static class C
{
static int x; // allowed here
}
}
class Test
{
public static void main(String… str)
{
A o=new A();
A.B obj1 =o.new B();//need of inclosing instance
A.C obj2 =new A.C();
// not need of reference of object of outer class….
}
}
I have a class with private fieds and also a static abstract inner class with the generic type extending the outer class type, that tries to access the outer class private fields but get's the following error:
- error: a has private access in Outer
- error: doSomething has private access in Outer
See code below:
public abstract class Outer extends SomeOuter
{
private Object a;
private void doSomething(){}
public static absract class Inner<T extends Outer> extends SomeOuter.SomeInner<T> {
public InnerMethod(T p) {
p.a; //error: a has private access in Outer
p.doSomething() //error: doSomething has private access in Outer
}
}
}
I'm compiling using jdk 1.7
Can anyone please tell me why am getting this error.
An Inner class can access private field of enclosing class and a static inner class can also access any private members of enclosing class .
The class itself isn't really "static"; there's no such thing as a static class. The
static modifier in this case says that the nested class is a static member of the outer
class. That means it can be accessed, as with other static members, without having
an instance of the outer class.
Since it is a static member , it is able to access outer class's private members , because within class private members are accessible.
eg.
class One
{
private int i=0;
class Two
{
void go()
{
System.out.println(new One().i); //accessible
}
}
}
class two
{
private int i=3;
static class one
{
void go()
{
System.out.println(new two().i); //accessible in static class
}
}
}
But here ,
Inner<T extends Outer> extends SomeOuter.SomeInner<T>
T is a class which extends Outer , doesn't mean it is inner.
That why it is giving error.
thats how private modifier works if you ever declare any method or variable as private than that things can not be accessed out side the class
A static embedded class is effectively an outer class. It can't access the private members of another class. See the accepted answer to:
Static nested class in Java, why?
Both the Object and the function you're trying to use are declared as private, which means they cannot be used outside the Object. If you want to use them in child classes as well, declare them as protected.
Changes the scope of the fields on the Outer class to protected so that classes extending Outer may access these fields.
public abstract class Outer extends SomeOuter
{
protected Object a;
protected void doSomething(){}
public static absract class Inner<T extends Outer> extends SomeOuter.SomeInner<T> {
public InnerMethod(T p) {
p.a; //error: a has private access in Outer
p.doSomething() //error: doSomething has private access in Outer
}
}
}
Thats what you have private modifier for. Though it is the inner class, it cannot access the private members of the outer class. So, declare it as protected, as you are extending the outer class to inner class
How would you declare a static variable in Super and instantiate it in subclass
Example
class A
{
static Queue<String> myArray;
public void doStuff()
{
myArray.add(someMethod.getStuff());
}
}
class B extends A
{
myArray = new LinkedList<String>();
}
class C extends A
{
myArray = new LinkedList<String>();
}
Obviously this doesnt work. But how would you go about declaring a variable; then doing some common functionality with the variable in the super class; Then making sure each subclass gets it own static LinkedList?
You can't do stuff along these lines. The closest you can do is to have an abstract (non-static) method in the superclass and do some stuff with it.
But in general, you cannot force subclasses to do anything static, and you cannot access subclasses' static fields from a superclass like you're trying to do.
Since, you have subclass-specific properties to manipulate, you can't do it in the superclass, and it is not logical to do it anyways. As was already mentioned, you can do something like this:
abstract class A {
public abstract void doStuff();
}
class B extends A {
static List<String>myArray = new LinkedList<String>();
public abstract void doStuff() {
// do B stuff
}
}
class C extends A {
static List<String>myArray = new LinkedList<String>();
public abstract void doStuff() {
// do C stuff
}
}
Static variable is bound to a class rather than an instance. If you need a separate static variable for subclasses, you need to declare them in each of your subclasses.
Why java compiler is not restricting from accessing a private attribute from other class?
I have inner class which has a attribute 'a' with modifier 'private'. I can able to access this variable with its instance variable out side the class. see the code below.
package com.test;
public class Test {
public Test() {
}
public static void main(String[] args) {
new Test().execute(); // test method
}
public void execute() {
InnerClass innerClassInstance = new InnerClass();
// accessing private member from other class instance, HOW?
System.out.println(innerClassInstance.a);
InnerStaticClass innerStaticClassInstance = new InnerStaticClass();
// accessing private member from other class instance, HOW?
System.out.println(innerStaticClassInstance.a);
}
private final class InnerClass {
private int a; // accessible only in InnerClass??
}
private final static class InnerStaticClass {
private int a; // accessible only in InnerClass??
}
}
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Sorry, I misread the question.
Looks at JLS http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-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.
So, a field in inner-class (which is obviously inside class body) can be accessed by outer class even if it's private.
See the Java language specification:
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.
your Inner class is a member of your Test class so, Test class can access private member of Inner class too.
Try like this it will give compile error
public class Test {
public Test() {
}
public static void main(String[] args) {
new Test().execute(); // test method
}
public void execute() {
InnerClass innerClassInstance = new InnerClass();
// accessing private member from other class instance, HOW?
System.out.println(innerClassInstance.a);
InnerStaticClass innerStaticClassInstance = new InnerStaticClass();
// accessing private member from other class instance, HOW?
System.out.println(innerStaticClassInstance.a);
}
}
class InnerClass {
private int a; // accessible only in InnerClass??
}
final class InnerStaticClass {
private int a; // accessible only in InnerClass??
}
These nested classes are meant for that .When you have private
members in a class ,we write nested class to do unit testing.
Given what I know of every other type of static feature of programming––I would think the answer is 'no'. However, seeing statements like OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass(); makes me wonder.
Yes, there is nothing in the semantics of a static nested type that would stop you from doing that. This snippet runs fine.
public class MultipleNested {
static class Nested {
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Nested();
}
}
}
See also
public static interface Map.Entry<K,V>
public static class AbstractMap.SimpleEntry<K,V>
Probably the most well-known nested type. Obviously instantiated multiple times.
Now, of course the nested type can do its own instance control (e.g. private constructors, singleton pattern, etc) but that has nothing to do with the fact that it's a nested type. Also, if the nested type is a static enum, of course you can't instantiate it at all.
But in general, yes, a static nested type can be instantiated multiple times.
Note that technically, a static nested type is not an "inner" type.
JLS 8.1.3 Inner Classes and Enclosing Instances
An inner class is a nested class that is not explicitly or implicitly declared static.
That is, according to JLS terminology, an inner class is one that isn't static. If it's static, then it's just a nested type.
So what does static mean?
static simply means that the nested type does not need an instance of the enclosing type to be instantiated.
See also
Java inner class and static nested class
Java: Static vs non static inner class
#polygenelubricants :
But in general, yes, a static nested
type can be instantiated multiple
times.
Just to be sure 100% of that I extended your snippet:
public class MultipleInner {
static class Inner {
private int state;
public int getState() { return state; }
public void setState(int state) { this.state = state; }
}
public static void main(String[] args) {
List<Inner> inners = new ArrayList<Inner>();
for (int i = 0; i < 100; i++) {
Inner inner = new Inner();
inner.setState(i);
inners.add(inner);
}
for (Inner inner : inners) {
System.out.println(inner.getState());
}
}
}
And of course the result is:
0
1
2
3
.
.
.
97
98
99
It is legal. The fact that the inner class is static gives you a benefit here; its instances are not bound to any instance of the containing class, so they can be freely instantiated (as long as the access qualifier allows it).
The price, however, is that the inner class can't use non static members/methods of the containing class.
Yeah you can make instances of it as many times as you want.
Maybe the reason why you see that, is because the programme thought about storing a reference somewhere. Though i agree with you seems strange :S
Inner class can use non static members/methods of containing class. It can use them only through an object reference of the enclosing class-
public class MultipleInner {
private int outerstate =10;
static class Inner {
private int state;
public int getState() { return state; }
public void setState(int state) { this.state = state; }
}
public static void main(String[] args) {
Inner inner = new Inner();
inner.setState(new MultipleInner().outerstate);
System.out.println(inner.getState());
}
}
So, inner class doesn't have to pay the price of not being able to access the non static members of the enclosing class.
Static nested classes are indeed instanced - they are, as said, top-level classes which live in the namespace of the 'outer' class, and obey static semantics respecting references to the 'outer' class. This code sample demonstrates :
public class OuterClass {
String outerStr = "this is the outer class!!" ;
public static class StaticNestedClass {
String innerStr = "default / first instance" ;
}
public static void main(String[] args) {
OuterClass.StaticNestedClass nestedObject1 = new OuterClass.StaticNestedClass();
OuterClass.StaticNestedClass nestedObject2 = new OuterClass.StaticNestedClass();
nestedObject2.innerStr = "second instance" ;
System.out.println(nestedObject1.innerStr) ;
System.out.println(nestedObject2.innerStr) ;
}
}
output:
default / first instance
second instance