Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么“班级”是期末考试?_Java_Security_Reflection_Decorator - Fatal编程技术网

Java 为什么“班级”是期末考试?

Java 为什么“班级”是期末考试?,java,security,reflection,decorator,Java,Security,Reflection,Decorator,在这里回答一个问题时,我想到了一个解决方案,如果能够扩展类类,那将是一个很好的解决方案: 这个解决方案包括尝试修饰类类,以便只允许包含某些值,在这种情况下,类扩展了一个具体的类C public class CextenderClass extends Class { public CextenderClass (Class c) throws Exception { if(!C.class.isAssignableFrom(c)) //Check whether

在这里回答一个问题时,我想到了一个解决方案,如果能够扩展
类,那将是一个很好的解决方案:

这个解决方案包括尝试修饰
类,以便只允许包含某些值,在这种情况下,类扩展了一个具体的类
C

public class CextenderClass extends Class
{
    public CextenderClass (Class c) throws Exception
    {
        if(!C.class.isAssignableFrom(c)) //Check whether is `C` sub-class
            throw new Exception("The given class is not extending C");
        value = c;
    }

    private Class value;

    ... Here, methods delegation ...
}
我知道这个代码不起作用,因为
是最终的,我想知道为什么
是最终的我理解这一定与安全性有关,但我无法想象扩展
是危险的。你能举几个例子吗?

顺便说一句,我能达到的理想行为的更接近的解决方案是:

public class CextenderClass
{
    public CextenderClass(Class c) throws Exception
    {
        if(!C.class.isAssignableFrom(c)) //Check whether is `C` sub-class
            throw new Exception("The given class is not extending C");
        value = c;
    }

    public Class getValue() {
        return value;
    }

    private Class value;

}

但是它缺乏透明装饰的美。

根据类中的评论只有Java虚拟机创建类 对象。

如果允许您扩展类,那么就会出现一个问题:是否允许您创建自定义类对象?。如果是,那么它将打破上述规则,即只有JVM才应该创建类对象。因此,您没有获得这种灵活性


PS:
getClass()
只返回已经创建的类对象。它不会返回新的类对象。

这是一个很好的问题,但只是一个更一般问题的实例,尽管@TheLostMind 4年前刚刚就JVM规则/限制做出了回应(从实现角度来看),但问题仍然存在:为什么JVM会提出这些规则?必须有一个合理的理由。我们必须从更抽象的层面(观点)来审视它

简短回答:
似乎所有这些都与类型安全有关,正如我们所知Java是一种强类型语言,不允许任何人改变这一事实

详细回答(有一定的上下文,以便每个人都能理解): 所有的故事都是从一开始的。 所提供的灵活性使对象的声明(静态)类型通常不同于其运行时(动态)类型。 运行时类型通常是静态类型的子类型。 e、 g

a的静态类型为AClass,赋值后a=b;它的运行时类型是AsubClass。这对执行消息时选择最合适的方法有影响

现在考虑给定的等级车辆。 下面

根类中的方法equals被定义为对对象标识的测试。 这是定义一般对象相等性的唯一有意义的方法。 也就是说,如果两个对象具有相同的标识,则它们是相等的

在特定类别中,更合适的平等含义可能更合适。在上述类别中,如果两辆车辆的VIN(车辆识别号)相等,则认为它们相等

因此,方法equals在 类车辆。这是对继承遗产的重新定义 方法被称为重写。 请注意,继承的方法参数的签名在子类中必须根据。 这造成了一个尴尬的局面,因为在类Vehicle中,我们希望引用参数的VIN字段,而Object没有这样的字段。这就是为什么类型转换(车辆)x指定将x视为车辆的目的。没有办法 静态验证此强制转换,因此编译器将生成动态检查。这是一个例子

为了使重写正确工作,要调用的方法由接收方对象的动态类型决定(也称为,并且是OO语言中动态绑定的最重要情况) e、 g

响应消息a.equals(b)调用的方法将是类Vehicle中重写的方法equals,因为a的运行时类型为Vehicle

在某些情况下,重写方法可能会有问题,因此不应允许重写。一个很好的例子是Java.lang.Object的getClass()。此方法在底层虚拟平台中有一个特定的实现,它保证调用此方法将确实返回方法接收方的类对象。 允许重写将对该方法的预期语义产生严重影响,从而在动态类型检查中产生不寻常的问题。这可能就是为什么getClass()被声明为final。 e、 g

最后,Java中的类是final,即不能扩展,因此它的任何方法都不能被重写由于类只有内省方法,这保证了类型系统在运行时的安全性,即类型信息不能在运行时发生变异

为了进一步扩展这个概念

基于接收方对象类型的方法动态分派(选择)是面向对象语言中的基本技术。 它带来了使整个面向对象范例工作的灵活性

通过继承向已经编译并运行的应用程序添加新类型只需要编译和链接新引入的类型,而不需要重新编译现有应用程序。然而,这种灵活性在效率上会带来一些损失,因为有关方法选择的决定会推迟到运行时。现代的 语言有高效的方法来动态调度方法,但是一些语言如C++和C语言试图通过提供静态绑定(方法选择)选项来避免相关的成本。在C#中,方法是静态绑定的,除非它们显式声明为虚拟。 e、 g

在C#中重写此方法将由显式关键字override指示。 e、 g

接收方是类对象的方法总是静态绑定的。 原因是该类的所有对象只有一个类对象。由于接收器在编译时已知,因此
AClass a = new AClass();
AsubClass b = new AsubClass(); //  AsubClass is derived from AClass
a=b;
public class Vehicle {
  private int VIN; // Vehicle Identification Number
  private String make;

  public boolean equals(Object x) {
    return (VIN == (Vehicle)x.VIN);
  }
  // other methods
}
Object a = new Object();
Object b = new Object();
Vehicle aV = new Vehicle();
Vehicle bV = new Vehicle();
a=aV; 
b=bV;
. . . 
a.equals(b)
. . .
public class Object {
  public final Class getClass();
  ....
}
public class Object {
  public virtual boolean equals(Object x);
  // other methods
}
public class Vehicle {
  private int VIN;
  private String make;

  public override boolean equals(Object x) {
    return (VIN == (Vehicle)x.VIN);
  }
  // other methods
}
public class Vehicle {
  // fields;
  public static int numberOfVehicles();
  // other methods
}