Java类成员(成员变量和方法)的覆盖与隐藏归纳

以前就知道重写override和重载overload的区别,平时也是逮着用就是了,Eclipse报错再说。

最近看一本书里面出现了重写、替换、覆盖、置换、隐藏、重载,简直乱得不行,归纳整理一下。

从全局来看,java只有重写、隐藏、重载3种,具体归纳如下:

基本概念:

方法签名:方法名+参数列表(参数类型、个数、顺序)。
=================================【重写】=================================

某些书又叫覆盖、替换、置换。本文统一叫重写。

只有实例方法可以被重写!重写后的方法必须仍为实例方法!(实例方法------重写------>实例方法)
成员变量和静态方法都不能被重写,只能被隐藏。

重写实例方法:超类Parent中有实例方法A,子类child定义了与A“相同签名和子集返回类型”的实例方法B,子类对象ChildObj只能调用自己的实例方法B。
                              即使将子类对象ChildObj转换为超类对象ParentObj,ParentObj依然只能调用重写后的实例方法B!
                              (超类对象ParentObj中的实例方法A已经被实例方法B覆盖了)

       

重写的语法规则如下:
(1)方法签名必须相同(参数类型、个数、顺序);
(2)对返回类型有要求,分2种情况:
     a.被重写方法的返回类型是基本类型:重写方法的返回类型必须“相同”。
                基本类型包括了(byte,short,int,long,float,double,char,boolean,其实还包括一个void类型),但要注意返回类型是封装类时属于下面的情况b。
     b.被重写方法的返回类型是引用类型:重写方法的返回类型应“相同”或是其“子类型”;
                引用类型包括了数组、string等一切非基本类型的类型(即类类型)。
(3)重写方法的访问权限不能小于被重写方法的访问权限,可以更广泛。如被重写方法是包访问权限,重写方法是public访问权限。
     重写方法可以改变其它的方法修饰符,如final、synchronized、native、strictfp。
     不管被重写方法中有无final修饰的参数,重写方法都可以增加、保留、去掉这个参数的final修饰符(参数修饰符不属于方法签名)。
(4)重写方法抛出的异常范围不能大于被重写方法抛出的异常的范围(也可以不抛出异常)。
(5)不能重写final方法。(final修饰符存在的意义就是防止任何子类重写该方法)
(6)不能重写static静态方法。(形式上可以写,但本质上不是重写,属于下面要讲的隐藏)
(7)如果一个方法不能被继承,则不能重写它。或者说:只有当方法可以被访问时才可以被重写。
     典型的就是超类的private方法。

对于(3)需要注意:
1.重写override对返回类型有要求,而重载overload对返回类型没有要求。
   重载可以改变返回类型。因为编译器通过对方法签名的识别即可静态编译出不同的方法。这也是java中重载与重写的区别之一。
2.严格来说,重写属于多态,因为是动态绑定(或称为动态联编),而重载是静态绑定,编译时即可确定。

=================================【隐藏】=================================

隐藏与覆盖在形式上极其类似(语法规则),但有着本质的区别。

只有成员变量(不管是不是静态)和静态方法可以被隐藏。

----------------------------成员变量------------------------

隐藏成员变量:超类Parent中有成员变量A,子类Child定义了与A同名的成员变量B,子类对象ChildObj调用的是自己的成员变量B。
                              如果把子类对象ChildObj转换为超类对象ParentObj,ParentObj调用的是超类的成员变量A!
                              注:1.隐藏成员变量时,只要同名即可,可以更改变量类型(无论基本类型还是隐藏类型)
                                       2.不能隐藏超类中的private成员变量,换句话说,只能隐藏可以访问的成员变量。
                                       3.隐藏超类成员变量A时,可以降低或提高子类成员变量B的访问权限,只要A不是private
                                       4.隐藏成员变量与是否静态无关!静态变量可以隐藏实例变量,实例变量也可以隐藏静态变量
                                       5.可以隐藏超类中的final成员变量。

 

----------------------------静态方法------------------------

隐藏后的方法必须仍为静态方法!(静态方法------隐藏------>静态方法)

隐藏静态方法:超类Parent有静态方法A,子类Child定义了与A“相同签名和子集返回类型”的静态方法B,子类对象ChildObj调用的是自己的静态方法B。
                              如果把子类对象ChildObj转换为超类对象ParentObj,ParentObj调用的是超类的静态方法A!

隐藏超类静态方法的语法规则与重写实例方法的规则几乎完全相同,只需要修改第(6)条为:(6)不能隐藏实例方法。。

示例代码:

[java] view plain copy

  1. class Animal {
  2. char hairColor=‘B‘;
  3. int legNumber=2;
  4. static boolean isHuman=true;
  5. public static void testClassMethod() {
  6. System.out.println("The class" + " method in Animal.");
  7. }
  8. public void testInstanceMethod() {
  9. System.out.println("The instance " + " method in Animal.");
  10. }
  11. }
  12. public class Cat extends Animal {
  13. static int hairColor=1;
  14. char legNumber=‘A‘;
  15. double isHuman=3.1415926E5;
  16. public static void testClassMethod() {
  17. System.out.println("The class method" + " in Cat.");
  18. }
  19. public void testInstanceMethod() {
  20. System.out.println("The instance method" + " in Cat.");
  21. }
  22. public static void main(String[] args) {
  23. System.out.println("========child class=========");
  24. Cat myCat = new Cat();
  25. System.out.println("myCat.hairColor="+myCat.hairColor);
  26. System.out.println("myCat.legNumber="+myCat.legNumber);
  27. System.out.println("myCat.isHuman="+myCat.isHuman);
  28. myCat.testClassMethod();
  29. myCat.testInstanceMethod();
  30. System.out.println("========child class ---> parent class=========");
  31. Animal myAnimal = myCat;
  32. System.out.println("========parent class=========");
  33. System.out.println("myAnimal.hairColor="+myAnimal.hairColor);
  34. System.out.println("myAnimal.legNumber="+myAnimal.legNumber);
  35. System.out.println("myAnimal.isHuman="+myAnimal.isHuman);
  36. myAnimal.testClassMethod();
  37. myAnimal.testInstanceMethod();
  38. }
  39. }

输出结果:

[java] view plain copy

  1. ========child class=========
  2. myCat.hairColor=1
  3. myCat.legNumber=A
  4. myCat.isHuman=314159.26
  5. The class method in Cat.
  6. The instance method in Cat.
  7. ========child class ---> parent class=========
  8. ========parent class=========
  9. myAnimal.hairColor=B
  10. myAnimal.legNumber=2
  11. myAnimal.isHuman=true
  12. The class method in Animal.
  13. The instance method in Cat.
时间: 2024-08-28 13:08:22

Java类成员(成员变量和方法)的覆盖与隐藏归纳的相关文章

Java 类中的变量和方法

1.类中定义的域变量可以被类中的所有方法访问. 2.方法中形式参数和定义的局部变量的作用域仅限于该方法中,局部变量在使用前必须进行赋值初始化. 3.如果局部变量和类中的域变量重名,则在方法中对同名变量改变的是局部变量. 4.在方法中如果要使用类的域变量,需要引入 this 关键字.

java变量和方法的覆盖和隐藏(翻译自Java Tutorials)

隐藏变量 在一个类里,如果一个变量的名字和父类的变量的名字一样,即使他们的类型不一样,那么在子类中,父类的同名变量无法直接通过变量名访问.但是,父类的同名变量可以通过super访问.一般来说,不推荐隐藏变量,这样会让代码难以阅读 覆盖和隐藏方法 对象实例方法 在一个对象实例方法中,如果子类有一个方法,它的签名(方法名字,方法的参数个数和类型)和返回值都和父类一样,那么就是覆盖父类的方法.子类覆盖的能力,允许一个类,继承父类的行为,根据需要修改某些行为.覆盖的方法,和父类对应的方法有一样的名字,一

Java 类中成员初始化顺序

Java 中的类成员 基本分为 静态成员, 实例变量  方法中特别的是静态方法和构造方法. 1.定义一个类 public class ClassLoaderTest { public int a ; public String b; private static int c; public  ClassLoaderTest(){ System.out.println("执行前:"+ a + "  "+ b); a = 10; b = "lisi"

Java 类的实例变量初始化的过程 静态块、非静态块、构造函数的加载顺序

Java 类的实例变量初始化的过程 静态块.非静态块.构造函数的加载顺序 先看一道Java面试题: 1 public class Baset { 2 private String baseName = "base"; 3 // 构造方法 4 public Baset() { 5 callName(); 6 } 7 // 成员方法 8 public void callName() { 9 // TODO Auto-generated method stub 10 System.out.p

分析java类的静态成员变量初始化先于非静态成员变量

分析java类的静态成员变量初始化先于非静态成员变量 依上图中当class字节码文件被jvm虚拟机加载到内存中依次经过 连接 验证:对字节码进行验证 准备:给静态变量分配内存并赋予变量类型各自的默认值(注:基本类型为0或false,对象为null,static final修饰的常量直接赋予相应的值) 解析:类中符号引用转换成直接引用 初始化:为类的静态变量/静态语句块初始化相应的值 而类的初始化契机是:类在被第一次主动使用的情况下,主动使用包括以下6中情况: 使用new关键字实例化对象时. 调用

Python 之面向对象:类和对象调用类中的变量和方法

面向对象的核心是对象,用对象来操控类里面的方法和变量,加上类还具有继承.封装.多态三大特性,提高了代码的复用性和规范性. 一.对象 调用类中的变量和方法 二 .类  调用类中的变量和方法 原文地址:https://www.cnblogs.com/tianpin/p/11283032.html

Java类的成员变量和局部变量

在Java中,成员变量和局部变量存在较大的差异性.首先,我们来看一下变量的分类图: 成员变量 成员变量被分为:类属性和实例属性. 类属性:定义一个属性时,不使用static修饰的就是实例属性, 实例属性:定义一个属性时,使用static修饰的是类属性. 类属性从这个类的准备阶段起开始存在,直到系统完全销毁这个类,类属性的作用域与这个类的生存范围相同: 而实例属性则从这个类的实例被创建开始存在,直到系统完全销毁整个实例,实例属性的作用域与对应实例的生存范围相同. PS:一个类在使用之前,要经过类加

java类中成员变量初始化后存放在堆内存中还是栈内存中?

答案是堆内存. 之前明明看过java类初始化过程的, 但一下子看到这样的题目,还是懵了. 百度后,那些帖子的回复各有各说, 脑袋都看得要塞住了,还是看书求证吧. 李刚的<疯狂Java>第128页开始,有一个类从初始化开始, 在内存发生什么变化的详细过程,这里简单记录一下. class Person{     String name;     static int eyeNum; } 上面这个Person类,有成员变量name和静态成员变量eyeNum了, 当执行下面语句: Person p1 

浅谈java类中成员的初始化顺序(一)

类被创建之后的成员的初始化顺序到底是怎么样的? 首先 不考虑继承 package com; public class DemoOne { /** * 关于类的初始化顺序 */ //不考虑继承结构的情况 private static int a=1; private String str="我被赋值了"; static{ //为什么static成员函数不能访问非static变量, 不能调用非static成员函数? //静态代码块独立于对象而存在 不依赖于对象存在 简单来说可以直接以类型名