-1

If I have something like

public class OwnerClass1{

   public class OwnedClass{
      // definition 1
   }

}

public class OwnerClass2{

   public class OwnedClass{
      // definition 2
   }

}

From a function that is implemented as below:

public <OwnedClass> boolean doStuff(OwnedClass example) {
   System.out.println(example.<???>);
   // example.getClass() returns "OwnerClass1$OwnedClass" etc here, so I guess getting this to string and trimming after $ would be one solution
   // example.getSuperClass() returns "java.lang.Object" here, so not what I need
}

How can I get the behavior as below:

doStuff(new OwnerClass1.OwnedClass());
// OwnerClass1

doStuff(new OwnerClass2.OwnedClass());
// OwnerClass2

Note: Code above is meant to give a rough idea of the structure, not to be compiled out of box.

ozgeneral
  • 6,079
  • 2
  • 30
  • 45
  • `example.super.getClass()` gives an error by underlining "example" and saying "class name expected here" – ozgeneral May 13 '19 at 08:32
  • Code won't compile, lose the `()` – Nicholas K May 13 '19 at 08:32
  • Possible duplicate of [Getting hold of the outer class object from the inner class object](https://stackoverflow.com/questions/1816458/getting-hold-of-the-outer-class-object-from-the-inner-class-object) – Lesiak May 13 '19 at 08:33
  • 2
    I don't get it. since you need two overloads of `doStuff` for this to compile : `void doStuff(OwnerClass1.OwnedClass ownedClass) {...)` and `void doStuff(OwnerClass2.OwnedClass ownedClass) {...}` you already know that Owner, no? – Eugene May 13 '19 at 08:34
  • 1
    Maybe try `getEnclosingClass()` instead of `getSuperClass`? Your `OwnedClass` doesn't extend `OwnerClass1`. – Amongalen May 13 '19 at 08:38
  • 2
    `public boolean doStuff(OwnedClass example)` is pretty much equivalent with `public boolean doStuff(Object example)`. Very confusing to have the generic type parameter named like this, better use `` or such. – Thilo May 13 '19 at 08:41
  • @Eugene, the project I am working on has more than 20 "OwnerClasses", so I wouldnt want to maintain a `doStuff` function each time someone creates another `OwnerClass` – ozgeneral May 13 '19 at 08:47
  • have you tried compiling the code as you have written it? when you declare a method that accepts `OwnedClass` - the compiler will ask you _which_ OwnedClass that is - so you are _forced_ to declare a method that will explicitly say which class that is. or, you have not shown the entire code in your question – Eugene May 13 '19 at 08:49
  • @Amongalen yes `example.getClass().getEnclosingClass()` was what I was looking for, thank you! you can post it as an answer and I'll accept it. – ozgeneral May 13 '19 at 08:49
  • @Thilo I dont have that liberty as I am building extra features to a large project with some legacy code. And although the example by itself seems redundant it actually makes sense in the context that it is implemented – ozgeneral May 13 '19 at 08:51
  • @Eugene no this is a simplified version I wrote directly as text to stackoverflow, OwnedClass actually extends an irrelevant class and so on but I trimmed those parts off – ozgeneral May 13 '19 at 08:53
  • 1
    you still don't get IMO. you have trimmed that most relevant part of your question, it seems, I voted to close this as un-clear... – Eugene May 13 '19 at 08:54
  • well I got my answer, so it must be clear enough to provide the needed information. I would say "leave it as it is" as `example.getClass().getEnclosingClass()` is what I was looking for and it might be to case for future googlers. – ozgeneral May 13 '19 at 08:56
  • @ozgeneral well the fact that OwnedClasses have a common interface is important here and without it your code is simply incorrect. If someone stumbles upon it by chance and assumes it is correct it will be troublesome, therefore I'd rather see this question be edited or deleted as well. – IcedLance May 13 '19 at 09:49
  • @IcedLance, In my opinion what I'm asking is clear, answer is also here, and having the example not compiling will not misdirect a user greatly. Therefore I consider this to be resolved. If you think not having this is better, you are welcome to delete the question but honestly I would have wanted to find something like this when I initially searched for an answer without knowing what terms to use in my search. PS. I added a note to be clear that example is not meant for actually compiling. – ozgeneral May 13 '19 at 10:37

3 Answers3

2

I understand that you want your unique doStuff method to act differently depending of the class on the actual class of the parameter you pass to it.

For this to be possible, OwnedClass1 and OwnedClass2 have to extend a common class or interface (that I guess you call OwnedClass). Otherwise your doStuffwill have to take an Object as param.

Then you can use instanceofto differenciate the classes.

Example with Object :

public boolean doStuff(Object example) {
    if (example instanceof OwnedClass1) {
       System.out.println("this is a class 1!");
    } else if (example instanceof OwnedClass2) {
       System.out.println("this is a class 2!");
    } else {
       throw new RuntimeException("Not supported : " + example.getClass());
    }
}

And if you are only interested in the short name of the class, then you could go like that :

public boolean doStuff(Object example) {    
       System.out.println("this is a " + example.getClass().getName());
}

or even

public boolean doStuff(Object example) {    
       System.out.println("this is a " + example.getClass().getName().replaceAll(".*\\.", ""));
}

HTH!

Highbrainer
  • 750
  • 4
  • 15
  • Yes that would work, thanks a lot for your answer. Only drawback is, there are actually a lot of different Owner classes and there will be more coming in future. So ideally this part would work without any maintenance. `example.getClass().getEnclosingClass()` seems to do what I was looking for with minimal effort, but you have my upvote! :) – ozgeneral May 13 '19 at 08:58
  • @ozgeneral yes, but once you've got the enclosing class by calling `getEnclosingClass()`, what can you possibly do with it? Presumably, you'd still have to do something like `if (enclosingClass == OnwerClass1.class) foo(); else if (enclosingClass == OwnerClass2.class) bar(); else if (...)...` so wouldn't this answer make it a bit easier? – DodgyCodeException May 13 '19 at 09:07
  • I pass it to an object which gets the class name, generates a unique metric name using that and sends a request to some server. So basically it is used to construct an object, not to have a class specific behavior. Thats why I dont need to have the if/else chunk if I have this – ozgeneral May 13 '19 at 09:09
1

Both OwnedClass sub classes could inherit from another class, that you pass to doStuff.

public class OwnerClass1 {

    public class OwnedClass  extends SuperOwnedClass {
        // definition 1
    }

}

public class OwnerClass2 {

    public class OwnedClass extends SuperOwnedClass {
        // definition 2
    }

}

public class SuperOwnedClass {

}

public boolean doStuff(SuperOwnedClass example) {
    System.out.println(example.<???>);
}

Or even better, let em implement interfaces.

Ali Ben Zarrouk
  • 1,891
  • 16
  • 24
  • Thanks for the answer, but I'm not at the liberty to change the general structure as I'm extending a large project with a lot of legacy code. So I agree this would be bit neater, but ideally I change the structure as minimally as possible. And main thing I'm looking for is `example.??>` part, which turned out to be `example.getClass().getEnclosingClass()` – ozgeneral May 13 '19 at 09:03
  • The thing for you is that you always know the enclosing class at compile time. You are importing a class, its not a parameter. – Ali Ben Zarrouk May 13 '19 at 09:08
  • Yes but same function will be called from different modules, and will be passed different objects. And ideally function (which is at a different module) just understands which class passes this object with minimal effort, so thats why `getEnclosingClass()` does the job in this case – ozgeneral May 13 '19 at 09:12
1

The OwnedClass doesn't extend the OwnerClass1, it only extends the Object class. Most likely you are looking for getEnclosingClass() method instead of getSuperClass().

public boolean doStuff(Object example) {
   System.out.println(example.getClass().getEnclosingClass());
}
Amongalen
  • 3,101
  • 14
  • 20
  • Thanks again, this was the simple keyword that I didnt know it existed! – ozgeneral May 13 '19 at 08:59
  • 1
    @ozgeneral apologies for being pedantic, but just in case future readers get confused, `getEnclosingClass` is not a keyword. It's just a normal method name belonging to the class `Class`. – DodgyCodeException May 13 '19 at 09:02
  • 1
    What is the point of the generic type on this method? It does not seem to be used anywhere? Why not just `boolean doStuff(Object example)` ? – Thilo May 13 '19 at 09:11
  • @Thilo I've just copied it from the question. Maybe OP uses it somewhere else in his code. Probably should be instead for clearance. – Amongalen May 13 '19 at 09:13
  • Removed the `` from the method signature. – Amongalen May 13 '19 at 09:17