(Java)实例化子类的不同方式

时间:2014-02-28 14:53:43

标签: java subtype

我有这两个类:

public class A {}
public class B extends A {}

在主课程中,我会声明:

A a = new B();
B b = new B();

a和b有什么区别?这是我们在java中所谓的子类型吗?

5 个答案:

答案 0 :(得分:5)

ab之间的区别在于a只能使用A类提供的公共API,即使它真的是B } type object,但使用b,您可以同时使用A的公共API以及B的公共API。

例如:

假设A和B的定义如下:

// A.java
public class A
{
  public void x()
  {
    z("X");
  }

  public void y()
  {
    z("Y");
  }

  protected void z(String message)
  {
    System.out.println(message);
  }
}

// B.java
public class B extends A
{
  public void a()
  {
    z("A");
  }

  public void b()
  {
    z("B");
  }
}

这是一个演示:

// Demo.java
public class Demo
{
  public static void main(String[] args)
  {
    A a = new B();
    B b = new B();

    // Can only call A's public methods
    a.x();
    a.y();
    // a.a(); Can't use
    // a.b(); Can't use

    // Can call all public methods
    b.a();
    b.b();
    b.x();
    b.y();
  }
}

答案 1 :(得分:1)

是的,之间存在差异。方法的可访问性因您使用的引用类型而异。

答案 2 :(得分:1)

A a = new B(); B b =新B();

  

a是A类的引用,b是B类的引用。超类总是可以用来指定子类对象。

     

引用a只能访问超类方法和属性

     

引用b能够访问超类及其自己的方法和属性

一个重要的事情是,功能和属性的可访问性将在运行时决定。

答案 3 :(得分:1)

以下两种情况

A a = new B();

a是B和A类的实例化。

而在

B a = new B();

a是B和B类型的实例化。

这里要注意的重要一点是(在第一种情况下)如果调用a.someMethod(),将调用B的方法,而不是A的方法(这称为动态绑定,而不是静态捆绑)。

答案 4 :(得分:0)

这是基本的继承。在B b = ...的情况下,您可以访问A和B提供的所有方法和变量,但在A情况下,您只能使用A案例中的方法和变量。

B在创建时被转换为A,但编译器不需要该信息。

public class A {
    int x;
}

public class B extends A {
    int y;
}

A a = new B();
B b = new B();

int c = a.x; //works
int c = a.y; //doesn't work
int c = b.y; //works
int c = b.x; //works

请记住,您始终可以在继承链中“向下”转换对象。但是你不应该向上转换一个对象,因为子类的变量可能会被使用,即使它们不存在,例如B b = new A();所以b.y很危险,因为B对象没有定义y变量。