简体   繁体   English

Java泛型和继承递归

[英]Java Generics and Inheritance recursion

I came across the following Java code that uses generics and inheritance. 我遇到了以下使用泛型和继承的Java代码。 I truly do not understand what the following snippet does: 我真的不明白以下代码片段的作用:

class A<B extends A<B>> {
   ...
}

What does this code do? 这段代码有什么作用?

(I got this from DBMaker in MapDB ) (我从MapDB中的DBMaker那里得到了这个)

It is almost clear and the question actually conists in two parts: 这几乎是清楚的,问题实际上分为两部分:

1) why B extends A ? 1)为什么B extends A

2) why A inside B extends A<B> has generic type B ? 2)为什么A内部B extends A<B>具有通用类型B

Answers for these parts will be: 这些部分的答案将是:

1) In particular example this class ( A ) is builder class (called DBMaker ), so most of its methods return some type, which extends this builder's class type. 1)在特定示例中,此类( A )是构建器类(称为DBMaker ),因此其大多数方法返回某种类型,这会扩展此构建器的类类型。 This explains, why B should extend A class. 这解释了为什么B应该扩展A类。

2) But, actualy, if we will hide for the second part ...extends A<B> , we will receive just class A<B> . 2)但是,实际上,如果我们将隐藏第二部分...extends A<B> ,我们将只收到class A<B> So A has type variable of type B . 因此A具有B类型的变量。 That is why in ...extends A<B> A is marked as type A having type variable B . 这就是为什么在...extends A<B> A被标记为具有类型变量B类型A

This tells that A needs derived definitions to be able to do some work: 这告诉A 需要派生定义才能做一些工作:

public abstract class A<T extends A<T>> {

   protected T instance;

   T getOne() {
       return instance;
   }
}

public class B extends A<B> {
   public B() {
       instance = this;
   }
}

public static void test() {
   B b = new B();
   b.getOne();
}

This is most commonly used in interface definitions, where one wants to explicitly use instances of classes implementing an interface in return types or in arguments and not the interface itself: 这在接口定义中最常用,其中一个人想要显式地使用在返回类型或参数中实现接口的类的实例,而不是接口本身:

public interface TimeSeries<T extends TimeSeries<T>> {
    T join(T ts);
}

public class DoubleTimeSeries implements TimeSeries<DoubleTimeSeries> {
    @Override
    public DoubleTimeSeries join(DoubleTimeSeries ts) {
        return null;
    }
}

So I did some tests to figure this one out, and here is my test cases to see how one could use such a generic case: 所以我做了一些测试来解决这个问题,这是我的测试用例,看看如何使用这样的通用案例:

public class A<B extends A<B>> {
    int x = 10;
    B test;

    void printX() {
        System.out.println(x);
    }

    void setB(B b) {
        test = b;
    }

    void printB() {
        System.out.println(test);
    }
}

public class B extends A<B> {

}

public class Run {
    public static void main(String[] args) {
        A<B> test = new A<B>();
        B myB = new B();
        test.printX();
        test.setB(myB);
        test.printB();
        myB.printB();

    }
}

I hope the code might be self explanatory. 我希望代码可能是自我解释的。 If not leave a comment and I will try and explain what is going on. 如果不发表评论,我会尝试解释发生了什么。 Look at the last line, myB.printB(), here we will get a null, because B has not yet been set for myB, but only for test. 查看最后一行myB.printB(),这里我们将得到一个null,因为尚未为myB设置B,但仅用于测试。 This demonstrates that we can have an infinite recursion into classes of B inside A (and inside B for that matter). 这表明我们可以无限递归到A中的B类(对于那个问题,在B内)。

we can say: 我们可以说:

myB.test.printB();

This will get an error (null pointer), but shows that we now have access to test in the A class from B, and we can go as deep as we want recursively with as many cases as we like. 这将得到一个错误(空指针),但表明我们现在可以从B中访问A类中的测试,并且我们可以根据需要递归到我们想要的尽可能多的情况。 So the A class kind of functions as a wrapper of infinitely many B classes. 所以A类的函数作为无限多B类的包装器。 Does this make sense? 这有意义吗?

This makes it easier when defining method return types such as this: 这使得在定义方法返回类型时更容易,例如:

class A<B extends A<B>> {
      public B getMe(){
            return (B) this;
      }
}

This tells Java compiler that you are in getMe() method returning a subclass of class A . 这告诉Java编译器你在getMe()方法中返回类A的子类。

class C extends A<C> {

}

C c = new C();
c.getMe(); //returns C

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM