首先说明一下结果:不可以,至少Java语言规范上说的是不可以。
今天遇到一个问题:向上转型是安全的,不需要进行强制类型转换。原因当然是子类是父类的超集,所以父类中的东西(成员变量和成员方法在子类中都有)
/**
* @description : 测试继承 <br>
* @author Administrator <br>
*/
class SuperClass {
public void show() {
System.out.println("Super");
}
}
class SubClass extends SuperClass {
public void show() {
System.out.println("Sub");
}
}
public class TestSubsSuper {
public static void main(String[] args) {
SuperClass sup = new SubClass();
sup.show();
}
}
上面的结果输出是Sub。
仔细看上面的类,SubClass继承了SuperClass,并重写了其中的show()方法,其实你可以使用@Override加上注解。在看main()方法中,我们创建了一个SuperClass引用,但是我们用的是new SubClass(),也就是一个父类的引用实际上指向的是子类的对象。其实在使用new SubClass()之前,虚拟机并不知道这个sup引用指向的是父类还是SubClass子类或者是其他子类,而只有在运行的时候才能确定。这也就解释了如果使用sup调用了一个父类中不存在的方法,他会编译报错
提示父类中就没有定义这个方法。从这也可以看出在运行之前他调用的是父类中的show()方法。这里有个概念就是后期绑定(即子类可能覆盖了父类中的方法,那么最终执行的是子类中覆写的方法还是父类自己本身的方法在编译期是不确定的,而在运行期才能确定(注:这是和重载不同的地方,重载是在编译期就已经确定了要执行哪个版本的方法))。但是到底他会执行哪个方法呢?是子类的还是父类的呢?
应该从两点进行考虑:
一、这个引用指向的是子类还是父类;
二、如果指向的是子类,子类有没有覆写父类的方法。
如果是:SuperClass sup = new SuperClass(),即创建的是一个父类对象,那么无论子类是否覆写了父类的方法,调用的始终是父类的方法。
如果是:SuperClass sup = new SubClass(),即创建的是一个父类引用,但实际指向的是子类的对象。那么就要看子类是否覆写了父类中的方法,如果覆写了,那么肯定调用的是子类中的方法;而如果没有覆写,那么则会去调用父类中的方法。
但是为什么会有下面的这种写法呢?如果我想调用子类的方法,我直接创建一个子类的对象,如果我想调用父类的方法,就直接创建一个父类对象不就行了吗?答案当然是可以的。但是有时候这可能会导致一些很繁琐的事情 ,接着上面的例子说:
public class TestSubsSuper {
public static void differentShow(SuperClass sup) {
sup.show();
}
public static void main(String[] args) {
differentShow(new SuperClass());
differentShow(new SubClass());
}
}
我新增加了一个方法,这个方法接收一个SuperClass类型的引用作为参数,并使用它调用了show()方法。如果按照前面我们说的,调用哪个类的方法,就创建一个该类的对象,那么相应的我就应当创建很多个differentShow()方法,每一个方法接收一种类型的参数,很明显这样显得很冗余。但是有了上面的这种形式的写法,我使用一个父类类型的引用作为参数,同时我可以接收一个子类类型的对象,然后会根据前面所说的动态绑定在运行时确定执行哪个版本的方法,这样会很方便。其实,这也就是面向对象的一个重要特性——多态。
再回到我们最初的问题,那么这个子类继承父类,会继承他的private成员吗?
首先看下Java language specification中的说明:
A class C inherits from its direct superclass and direct superinterfaces all abstract and
non-abstract methods of the superclass and superinterfaces that are public, protected,
or declared with default access in the same package as C,
and are neither overridden (§8.4.8.1) nor hidden (§8.4.8.2) by a declaration in the class.
再看下Java 官方学习文档中的说明:
Private Members in a Superclass
A subclass does not inherit the private members of its parent class.
However, if the superclass has public or protected methods for accessing its private fields,
these can also be used by the subclass.
A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited
by a subclass has indirect access to all of the private members of the superclass.
从上面我们可以看出其实子类继承父类的东西,不会继承其private成员。但是为什么不能继承private呢?
以下是个人理解:
首先我们知道,private类型的成员变量或者方法默认是final的,对于final方法,是不允许覆盖的。如果子类可以继承父类的private方法,那么自然而然可以覆写其中的方法,那也就与final冲突。
另外,对于private声明的成员在本类之外是不可以被访问的。但是如果子类继承了的话,那也就意味着可以访问父类的private,这和private又有冲突,所以其实是不会继承的。
但是,注意这一句话:However, if the superclass has public or protected methods for accessing its private fields,
these can also be used by the subclass.
class SuperClass {
private String str;
public void setStr() {
str = "Hello";
System.out.println(str);
}
public void show() {
System.out.println("Super");
}
}
public class TestSubsSuper {
public static void main(String[] args) {
SuperClass sup = new SubClass();
sup.setStr();
}
}
上面的那句话的意思如果父类中有public 或者 protected方法访问了父类中的private成员,那么子类也就可以通过这个方法间接访问父类的private成员。(也就是说父类的private成员在类外不是绝对不可访问的)
以上就是所有内容,如果有说的不对的地方,恳请批评指正,以免给他人造成错误的理解,不胜感激。
相关推荐
- 当子类和父类位于同一包中时,子类可以继承父类中的所有非私有成员,包括`protected`和`public`成员。 - `private`成员是不可见的,所以子类不能直接访问父类的`private`成员。但是,可以通过在父类中提供公共的...
Java 中子类重写父类的方法是面向对象编程的核心概念之一。子类可以重写父类的方法,以改变或扩展父类的行为。但是,子类重写父类的方法需要遵守一定的规则,以避免编译器错误和运行时异常。 A. 重写规则之一:重写...
如果类中没有定义任何构造器,Java编译器会自动为类提供一个默认的无参构造器。 - 如果类定义了一个或多个带有参数的构造器,编译器将不再提供默认无参构造器。因此,如果子类需要调用父类的构造器,必须通过`super...
- 继承中子类可继承父类的除private之外的所有属性。 15. **简答题答案**: - 八大基本数据类型:byte、short、int、long、float、double、boolean、char。 - 对象是类的实例,类是对象的蓝图,对象拥有类定义的...
在Java编程语言中,子类继承父类是实现代码复用和扩展功能的重要手段。当一个子类实例化时,其实例化过程涉及到多个步骤,这些步骤不仅包括自身的构造器执行,还包括对父类构造器的调用。下面将详细阐述Java中子类...
子类并不能直接继承父类的构造函数,而是通过调用父类的构造函数来初始化父类部分的状态。选项**B**错误。 #### 十五、Java访问控制修饰符 - **知识点**: 选择题15考查Java中的访问控制符。Java提供了四种访问级别...
这个例子说明了Java中子类可以访问父类的非私有属性和方法。 例子11探讨了访问修饰符`protected`的使用。在`Father`类中,`height`是私有的(`private`),`money`是受保护的(`protected`),`weight`是公共的(`...
解释:子类可以继承父类的成员,但是子类也可以有自己的成员,这样子类的成员数目可能大于父类的成员数目。 5. 抽象方法必须在抽象类中,所以抽象类中的方法都必须是抽象方法。() 解释:抽象方法可以在抽象类中...
下面将详细讲解Java中子类继承的概念、语法以及相关的知识点。 1. **继承的概念** 继承是一种“is-a”关系,表示一个类是另一个类的一种特殊形式。比如,`Car` 是 `Vehicle` 的一种,因此 `Car` 类可以继承 `...
`private`成员只能在同一个类中访问,而`public`成员可以被任何其他类访问。没有修饰符的成员默认为`private`。封装的例子包括`shoutNum`属性的读写方法`getShoutNum()`和`setShoutNum()`。 继承是面向对象的另一个...
6. **继承特性**:Java中子类可以继承父类,并且可以作为另一个类的父类。子类可以访问父类的非私有属性和方法,但不能访问私有属性。子类继承父类的方法后,访问权限保持不变。 7. **循环结构**:`do-while`循环在...
15. **由继承性可知,程序中子类拥有的成员数目一定大于等于父类拥有的成员数目。** - 错误。子类可能不会添加新的成员变量或方法,因此其成员数目不一定多于父类。 16. **Java语言中的数组元素下标总是从0开始,...
Java 中子类和父类构造器的使用 - **构造器调用顺序**:理解构造器链式调用的过程,包括如何使用 `super()` 调用父类构造器。 - **this 和 super 的区别**:区分 `this()` 和 `super()` 的使用场景。 - **实例化...
在Java中,一个类可以通过extends关键字继承另一个类的所有公开(public)和受保护(protected)成员。子类可以继承父类的方法和属性,并且可以根据需要覆盖或扩展这些方法。这种方式支持了代码的复用性和可扩展性。 - ...
4. **多重继承**:Java不支持多重继承,即一个类不能同时继承多个父类。但是,一个类可以实现多个接口,因此选项B正确。在Java中,类与接口之间使用`implements`关键字。 5. **close()函数**:在输出数据流中,`...
在本Java OOP实验中,我们探讨了三个主要问题,涉及类的设计、继承以及方法的实现。以下是每个问题的详细解答: **Q1. 扩展Point2D类** 初始的`Point2D`类已经定义了二维平面上的一个点,包含两个坐标`x`和`y`。...
Java中子类与超类的构造函数 - **构造函数调用**:子类构造函数必须显式调用超类构造函数。 - **super关键字**:使用super关键字调用超类构造函数。 - **构造顺序**:先执行超类构造函数,再执行子类构造函数。 #...