Is there something equivalent for StaticClass::new for inner class given the outer class instance?
Edit:
I.e. if I have
class Outer {
class Inner {
}
}
I can do Outer o = new Outer(); Inner i = o.new Inner() in old Java. How can I express the o.new Inner() as function reference.
According to the Oracle tutorials, there are four kinds of method references:
Reference to a static method
ContainingClass::staticMethodName
Reference to an instance method of a particular object
containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type
ContainingType::methodName
Reference to a constructor
ClassName::new
References to a local/nested class are not listed, so I would assume it's not supported.
You can use the java.util.function.Supplier to trigger the usage of lambdas in order to obtain an instance of the nested class:
Outer outer = new Outer();
Supplier<Outer.Inner> supplier = () -> outer.new Inner();
The Chapter 15.13. Method Reference Expressions in the JLS contains a somewhat cryptic statement about this:
The immediately enclosing instance of a new inner class instance (§15.9.2) is provided by a lexically enclosing instance of this (§8.1.3).
This basically means that a method reference to the constructor of an inner class is possible in a method of the outer class, like in this example
import java.util.function.Supplier;
class Outer
{
public class Inner
{
}
void example()
{
Supplier<Inner> s = Inner::new;
}
}
But the JLS does not mention any alternative, so one has to assume that it is simply not possible to provide the enclosing instance in any other form than being this.
For static nested class, you can refer to it using outer class - OuterClass.NestedClass::new:
public class Main {
public static void main(String[] args) {
int[] array = {1, 2, 3};
Arrays.stream(array).forEach(A.B::new);
}
}
class A {
public A(int x) {
System.out.println("A created, x = " + x);
}
public static class B {
public B(int x) {
System.out.println("B created, x = " + x);
}
}
}
For inner class (nested non-static class), you can do outerInstanceName.new InnerClass(...):
public class Main {
public static void main(String[] args) {
int[] array = {1, 2, 3};
A a = new A(500);
Arrays.stream(array).forEach(x -> a.new B(x));
}
}
public class A {
public A(int x) {
System.out.println("A created, x = " + x);
}
public class B {
public B(int x) {
System.out.println("B created, x = " + x);
}
}
}
My IDE suggests me to convert x -> a.new B(x) into A.B::new, but this doesn't compile, because B is not static - it belongs not to the class A but to the instance of class A. So answering your question - I think it is not possible and you will have to use outerInstanceName.new InnerClass(...).
Related
public class MyClass {
int x=9;
public static void main(String args[]) {
MyClass myClass = new MyClass();
myClass.test();
}
public void test(){
int x=10;
class InnerClass{
int x = 11;
void print(){
int x = 12;
System.out.println(x);
System.out.println(this.x);
System.out.println(MyClass.this.x);
System.out.println("MyClass => test() => x :" + "?");
}
}
InnerClass innerClass = new InnerClass();
innerClass.print();
}
}
How to call MyClass test() method local variable x inside the InnerClass print() method. What i can write in place of ? in last System.out.println() method in order to get the value of test() x.
Unfortunately in Java you can't.
The only way to access the x in MyClass::test would be to rename both variables in your inner class and in your inner class method into something else.
There is no need though to rename the outer class field x as InnerClass::print would consider the variable in the most-inner scope.
Although this snippet is for demonstration purposes, better practice would have you have different and more significant names for each variable.
That works fine for me:
public class Outerclass {
public static void main(String args[]) {
Outerclass outer = new Outerclass();
outer.outerMethod();
}
// method of the outer class
void outerMethod() {
int num = 23;
// method-local inner class
class MethodInnerClass {
public void print() {
System.out.println("This is method inner class "+num);
}
}
// Accessing the inner class
MethodInnerClass inner = new MethodInnerClass();
inner.print();
}
}
To print outer class variable use
MyClass.this.x
When we define inner classes, I understand that static inner classes are accessed with the outer class and inner member class exist with the instance of the outer class.
The confusion is, if I want to hold an instance of an non-private inner member class, then the variable declaration goes like:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
How outer class is able to reference the inner member class like this? What is happening here?
Sample Code:
public class NestedClasses {
public static void main(String[] args) {
A.B b = new A().new B(); // <- How A is directly accessing B, B is not defined as static.
A.StaticClass staticClass = new A.StaticClass();
}
}
class A {
static int x;
int y;
A() {
System.out.println(this.getClass().getName());
}
static class StaticClass {
StaticClass() {
System.out.println(this.getClass().getName());
}
}
class B {
B() {
System.out.println(this.getClass().getName());
}
}
}
I working on a sample problem of over-ridding hashCode and equals method but getting an error: "No enclosing instance of type CustomHashCodeExample is accessible. Must qualify the allocation with an enclosing instance of type CustomHashCodeExample (e.g. x.new A() where x is an instance of CustomHashCodeExample)."
I wrote an inner class HashPerson and I am getting this error when I am trying to instantiate this inner class in another method called testHashCodeOverride().
public static void testHashCodeOverride(){
System.out.println("\nTest HashCode Override Method");
System.out.println("==================================\n");
HashPerson william = new HashPerson("willy");
HashPerson bill = new HashPerson("willy");
}
This code works fine, even though I dont see static inner class or instantiation of outer class, confused :(
public class HashCodeExample {
public static void testHashCodeOverride() {
HashPerson william = new HashPerson("Willy");
HashPerson bill = new HashPerson("Willy");
System.out.println("Hash code for william = " + william.hashCode());
System.out.println("Hash code for bill = " + bill.hashCode());
HashMap table = new HashMap();
table.put(william, "Silly");
if (table.containsKey(william)) {
System.out.println(table.get(william));
} else {
System.out.println("Key " + william + " not found");
}
if (table.containsKey(bill)) {
System.out.println(table.get(bill));
} else {
System.out.println("Key " + bill + " not found");
}
}
class HashPerson {
private static final int HASH_PRIME = 1000003;
public HashPerson(String name) {
this.name = name;
}
public String toString() {
return name;
}
public boolean equals(Object rhs) {
if (this == rhs)
return true;
// make sure they are the same class
if (rhs == null || rhs.getClass() != getClass())
return false;
// ok, they are the same class. Cast rhs to HashPerson
HashPerson other = (HashPerson) rhs;
// our test for equality simply checks the name field
if (!name.equals(other.name)) {
return false;
}
// if we get this far, they are equal
return true;
}
public int hashCode() {
int result = 0;
result = HASH_PRIME * result + name.hashCode();
return result;
}
private String name;
}
}
I think you want to declare the HashPerson class as static. Otherwise it can only be instantiated in the context of the containing class, either in a method of the containing class or using code like this:
ContainingClass container = new ContainingClass();
HashPerson william = container.new HashPerson("willy");
Actually, my rule-of-thumb is to make any nested class static, unless I have a special reason not to. This is also more efficient, because non-static nested classes (called inner classes) always contain an implicit reference to the containing object.
You need to either make your inner class static, or refer to it through an instance of the outer class. Most likely you just want to make your inner class static.
Non-static members of a class (variables, methods, inner classes) are per instance of the class. Therefore, when accessing non-static members from a static context (such as a static method like testHashCodeOverride), you need to specify an instance of the enclosing class.
As i can see there could be different possible ways to instantiate the Inner Classes
Static Inner Class : When Inner class is static, let say code looks like as describe.
class OuterClass
{
static int outer_x = 10;
int outer_y = 20;
// static nested class
static class StaticNestedClass {
void display() {
}
}
}
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
or Just this could be sufficient for static classes
new StaticNestedClass();
Local inner Classes (Non Static) : Inner Classes which are not static, one good thing with local inner classes that they can access all private data members of enclosed class.
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Anonymous Inner Class (implementing Interface) : This type of classes generally hidden, One can't directly see the Class{...} block in code , That is why known as Anonymous Inner Class. Here describes how to instantiate it in case inner class implementing an interface Runnable Interface.
Runnable r = new Runnable()
{
//This is Anonymous Class
public void run() {
System.out.println("Child Thread");
}
};
Anonymous Inner Class (Extending One Class):We can have an anonymous inner class that extends a class, Here i am taking example of Thread Class,
Thread t = new Thread(new Runnable()
{
//Anonymous Inner class
public void run() {
System.out.println("Child Thread");
}
});
Anonymous Inner class that defines inside method/constructor argument : Inner Classes could be define within methods as well, here giving example how can we define and instantiate it within argument
public static void main(String[] args)
{
//Here we are using Anonymous Inner class
//that define inside argument, here constructor argument
Thread t = new Thread(new Runnable()
{
public void run()
{
System.out.println("Child Thread");
}
});
t.start();
If I have an inner class e.g.
class Outer{
class Inner{}
}
Is there any way to check if an arbitrary Object is an instance of any Inner, regardless of its outer object? instanceof gives false when the objects are not Inners from the same Outer. I know a workaround is just to make Inner a static class, but I'm wondering if what I'm asking is possible.
Example:
class Outer{
Inner inner = new Inner();
class Inner{}
public boolean isInner(Object o){
return o instanceof Inner;
}
}
Outer outer1 = new Outer();
Outer outer2 = new Outer();
boolean answer = outer1.isInner(outer2.inner); //gives false
And what about?
public static boolean isInnerClass(Class<?> clazz) {
return clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers());
}
The method isMemberClass() will test if the method is a member (and not an anonymous or local class) and the second condition will verify that your member class is not static.
By the way, the documentation explains the differences between local, anonymous and nested classes.
Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.
o instanceof Outer.Inner gives false when o is an instance of an Inner of any Outer other than the one you're calling it from.
This doesn't happen for me - I get true for o instanceof Inner regardless of which particular enclosing instance of Outer the o belongs to:
class Outer {
class Inner {}
void test() {
// Inner instance that belongs to this Outer
Inner thisInner = new Inner();
// Inner instance that belongs to a different Outer
Outer other = new Outer();
Inner otherInner = other.new Inner();
// both print true
System.out.println(thisInner instanceof Inner);
System.out.println(otherInner instanceof Inner);
}
public static void main(String[] args) {
new Outer().test();
}
}
Tested with both Java 6 and 7.
Did you try using getEnclosingClass():
Returns the immediately enclosing class of the underlying class. If the underlying class is a top level class this method returns null.
Outer.class.equals(object.getClass().getEnclosingClass())
Getting the correct enclosing class of the object , IMHO is not so easy . Read this.
Somewhat of a hack would be :
object.getClass().getName().contains("Outer$");
you could always:
getClass().getName()
and do a String comparison.
EDIT : to account for inheritance (among inner classes? who would do that?!) you could always loop through getSuperclass() and check for them as well, and even go after implemented interfaces.
The java.lang.Class.getEnclosingClass() method returns the immediately enclosing class of the underlying class. If this class is a top level class this method returns null.
The following example shows the usage of java.lang.Class.getEnclosingClass() method:
import java.lang.*;
public class ClassDemo {
// constructor
public ClassDemo() {
// class Outer as inner class for class ClassDemo
class Outer {
public void show() {
// inner class of Class Outer
class Inner {
public void show() {
System.out.print(getClass().getName() + " inner in...");
System.out.println(getClass().getEnclosingClass());
}
}
System.out.print(getClass().getName() + " inner in...");
System.out.println(getClass().getEnclosingClass());
// inner class show() function
Inner i = new Inner();
i.show();
}
}
// outer class show() function
Outer o = new Outer();
o.show();
}
public static void main(String[] args) {
ClassDemo cls = new ClassDemo();
}
}
Output
ClassDemo$1Outer inner in...class ClassDemo
ClassDemo$1Outer$1Inner inner in...class ClassDemo$1Outer
I was googling for finding out better answers, to find out that there are none out there.
Here is what I have which works pretty well:
public static boolean isStatic(Class klass) {
return Modifier.isStatic(klass.getModifiers());
}
/**
* Non static inner class
*/
public static boolean isInnerclass(Class klass) {
return klass.getDeclaringClass() != null && !isStatic(klass);
}
Will return true for local inner classes. isMemberClass and others do not work for this purpose.
Is there any way to acess a superclass member hidden by a subclass member using object of subclass in another class.
public class A {
int i, j;
A() {
i = 5;
j = 5;
}
}
public class B extends A {
int i;
B() {
super();
i = 10;
}
}
class TestEx {
public static void main(String[] args) {
B obj = new B();
// i from B
System.out.println(obj.i);
}
}
i need to acess i from A in testEx using obj..
same doubt is present in the case of non-static inner class.. anyway to acess variable of OuterClass in InnerClass with same name that of one in InnerClass
As simple as ((A)this).i from within the class B's instance methods or, even simpler,
A obj = new B();
System.out.println(obj.i);
Why? Because nothing except instance methods is subject to dynamic binding and overriding. The class B has all the instance variables of its ancestors.
public static void main(String[] args){
B obj=new B();
//i from B
System.out.println(((A)obj).i);
}
Expose your classes get methods via polymorphism to get the value of A's i from the instance invoked by B object. This is what you topic title is implying.
provide public get/set methods in both classes, then sit still relax and call it up.