java—将对象强制转换为t类型的类

p5cysglq  于 2021-07-08  发布在  Java
关注(0)|答案(2)|浏览(1243)

假设我有一个空类叫做 ClsA() ,它的一个子类称为 ClsB() 像这样:

public static class ClsA {}

public static class ClsB extends ClsA {}

假设我们现在有一个clsa类型对象的arraylist,我想计算arraylist中有多少元素实际上是clsa或clsb类型的。通过一些搜索,我发现以下函数非常有效:

public static <T> int countInstances(ArrayList<?> list, Class<T> cls) {
        int count = 0;
        for(Object o : list) {
            if(cls.isInstance(o)) {
                count++;
            }
        }
        return count;
    }

实际上,下面的示例main方法确实给出了正确的输出。

public static void main(String[] args) {
    // write your code here
    ArrayList<ClsA> test = new ArrayList<>();
    test.add(new ClsA());
    test.add(new ClsB());
    test.add(new ClsA());
    test.add(new ClsB());
    int result = countInstances(test,ClsB.class);
    System.out.println(result);
}

但是,假设clsb现在定义如下:

public static class ClsB extends ClsA {
    private final String type;
    public ClsB(String type) {
        this.type = type;
    }

    public String getType() {return type;}
}

我现在要计算给定arraylist中存在多少特定类型的clsb示例。在登记我的 countInstances() 如果一个元素属于给定的类(在本例中为clsb),我还希望能够检查给定给方法的类型是否与元素的类型匹配。有没有什么方法可以让你 Object o 因为编译器并不真正知道它的实际类型,所以将其转换为给定类的示例?
到目前为止我已经到了这一步:

public static void main(String[] args) {
        // write your code here
        ArrayList<ClsA> test = new ArrayList<>();
        test.add(new ClsA());
        test.add(new ClsB("t1"));
        test.add(new ClsA());
        test.add(new ClsB("t2"));
        int result = countInstances(test,ClsB.class,true,"t1");
        System.out.println(result);
    }

    public static <T> int countInstances(ArrayList<?> list, Class<T> cls, boolean checkForType, String type) {
        int count = 0;
        for(Object o : list) {
            if(cls.isInstance(o)) {
                if(!checkForType) count++;
                else {}// somehow cast o into the given class (?)
            }
        }
        return count;
    }
zbwhf8kr

zbwhf8kr1#

是的,有 cls.cast(o); 它会做到的,会给你一个 T (因为 clsClass<T> ,和 cast(Object o) 方法 j.l.Class 定义为返回 T . 它的行为就像cast操作符一样,因为它什么也不做:它只是Asserto实际上是这个类的一个示例(因此,创建为 new This() 或者 new SomeSubtypeOfThis() ). 如果是,它什么也不做。如果不是,则抛出classcastexception。在任何情况下都不会发生转换。
这没用;毕竟,t仍然只是一个物体。这不会给你打电话的权力 getType() 在你的 o -因为 T 没有界限,t除了 java.lang.Object 已经有了。
一般来说,你所从事的是结构类型:不管是什么 ClsB 重要的是,它有一个名为 getType .
这很糟糕。
这意味着 public interface Camera { public void shoot(Person p); } 以及 public interface Gun { public void shoot(Person p); } 在这样一个系统中,你是可以互换的,因此你会意外地把某人的头打掉。
类型(类、接口等)不受此问题的影响,因为它们有一个名称空间-一个包头,这使它们有效地唯一。因此,一个方法不应该被认为有任何意义,除非该方法是在它所处类型的上下文中。
因此,你能做的,是这样的:

public class ClsA {
    public String getType() { .... }
}

public class ClsB extends ClsA { .... }

public static int countInstances(ArrayList<?> list, Class<?> cls) {
    int count = 0;
    for (Object o : list) if (cls.isInstance(o)) count++;
    return count;
}

对于包含一个clsa示例和一个clsb示例的列表,上面将返回“2”,然后您通过 ClsA.class 作为第二个参数。
毕竟,里昂证券的一个示例也是里昂证券的一个示例。
如果您正在寻找“1”的答案,那么您正在寻找:

for (Object o : list) {
    if (o != null && o.getClass() == cls) count++;
}

然后对于“gettype”方法,我们必须将该方法链接到实际类型,因为否则你就是在打人,这很糟糕。所以,我把 getType() 方法,然后我们要求您传递一个clsa的列表:

public static int countInstancesWithType(List<? extends ClsA> list, String type) {
    int count = 0;
    for (ClsA o : list) {
        if (type.equals(o.getType())) count++;
    }
    return count;
}

请注意,可以使用 ArrayList<ClsA> 或者一个 ArrayList<ClsB> -两者都可以。 <? extends ClsA> 使之成为可能;这个 ? extends 这很重要。没有它, new ArrayList<ClsB>() 无法作为第一个参数传递。
如果你想把这两个想法结合起来,那就是。。一种奇怪的关注点和声音的混合,听起来像是在java中使用结构化类型的概念,或者是一些黑客试图实现动态类型。停止那样做;java不是那种语言,它会一直伤害到我们,最终的结果会是非惯用的、难以维护的和难以阅读的代码。找到一种java风格的方法来做你正在做的事情。但是,不要说我没有警告你:

public static int countInstancesWithType(List<?> list, String type) {
    int count = 0;
    for (Object o : list) {
        if (!(o instanceof ClsA a)) continue;
        if (type.equals(a.getType())) count++;
    }
    return count;
}
// NB: This uses java15 features. Without java15, you'd have to
// spend an extra line or two to cast ClsA separately.

试图一概而论是没有意义的 ClsA 在这里,因为这样做可以消除代码实现这一点的能力 ClsA 示例具有 getType() 方法。

yyhrrdl8

yyhrrdl82#

这个怎么样(请参见countinstances的更改签名)。

public static void main(String[] args) {
    // write your code here
    ArrayList<ClsA> test = new ArrayList<>();
    test.add(new ClsA());
    test.add(new ClsB("t1"));
    test.add(new ClsA());
    test.add(new ClsB("t2"));
    int result = countInstances(test,ClsB.class,o -> o.getType().equals("t2"));
    // count all
    //int result = countInstances(test,ClsB.class,o -> true);
    System.out.println(result);
}

public static <T> int countInstances(ArrayList<?> list, Class<T> cls, Predicate<T> test) {
    int count = 0;
    for(Object o : list) {
        if(cls.isInstance(o)) {
            if (test.test((T)o)) count++;
        }
    }
    return count;
}

这不回答你的职位的标题,但我猜这是你正在寻找的。

相关问题