-4

Can I use a double colon two times?

Sample I have 3 class

Class A {
   String name;
   B classB;
}

Class B {
  String age;
  C classC;
}
Class C {
  String location;
}

I need to use A::getClassB::getClassC::getLocation

Is this possible?

Matthias
  • 4,481
  • 12
  • 45
  • 84
Fabio Ebner
  • 2,613
  • 16
  • 50
  • 77
  • 8
    Why you do not try it – Jens Aug 03 '17 at 13:33
  • 1
    Should be possible only if you declare `B`, `C` and `location` as `static` and the corresponding methods static as well. `::` is for statics – ACV Aug 03 '17 at 13:34
  • 6
    @ACV it is not true that method references can only reference `static` methods. – Jesper Aug 03 '17 at 13:35
  • @Jesper, you are right. `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` – ACV Aug 03 '17 at 13:42
  • According to the [language spec](http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-MethodReference), it might be possible (MethodReference is a type of Primary, which can be the LHS), but in practice, it seems not to work. E.g., `(Object::toString)::toString` does not compile, and `toString` should be a method of whatever the first part returns. – tobias_k Aug 03 '17 at 13:43
  • Using static is one way to go. – ACV Aug 03 '17 at 13:43

1 Answers1

1

I need to use A::getClassB::getClassC::getLocation

Is this possible?

Not as such.

You're talking about method reference syntax, which designates a method via its name and either the name, the type, or an instance of a class or interface to which it belongs. According to the Java Tutorial, there are exactly four forms they can take:

  1. Reference to a static method: ContainingClass::staticMethodName
  2. Reference to an instance method of a particular object: containingObject::instanceMethodName
  3. Reference to an instance method of an arbitrary object of a particular type: ContainingType::methodName
  4. Reference to a constructor: ClassName::new

Type and variable names cannot contain colons, so the only one of those that could conceivably afford chaining colons would be (2), where you would then be forming a reference to a method of a lambda. That does not appear to be what you want to do.

If your classes actually had getter methods such as you seem to want to use, then you should be able to write a lambda similar to your expression:

a -> a.getClassB().getClassC().getLocation()

Alternatively, you should be able to write a method reference of this form:

myA.getClassB().getClassC()::getLocation

Those have different significance, as this example code demonstrates:

import java.util.function.Function;
import java.util.function.Supplier;

public class X {
    // Note the types declared for these objects:
    Function<A, String> f1 = a -> a.getClassB().getClassC().getLocation();    
    Supplier<String> f2 = new A().getClassB().getClassC()::getLocation;
}

class A {
   String name;
   B classB = new B();

   public B getClassB() { return classB; }
}

class B {
  String age;
  C classC = new C();

  public C getClassC() { return classC; }
}

class C {
  String location;

  public String getLocation() { return location; }
}

Note in particular that a -> a.getClassB().getClassC().getLocation() is a lambda that that computes a location string for an A given as input, whereas myA.getClassB().getClassC()::getLocation is a reference to the getLocation() method of the particular C obtained by invoking myA.getClassB().getClassC() (at the point where the method reference is instantiated, not the point where it is used). I suspect that one of those is what you actually want.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157