博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA中方法和变量在继承中的覆盖和隐藏(一)
阅读量:5263 次
发布时间:2019-06-14

本文共 3348 字,大约阅读时间需要 11 分钟。

 

我们知道,在JAVA中,子类可以继承父类,如果子类声明的方法与父类有重名的情况怎么办,大伙儿都知道要是重写,但是实际上这又分为两种情况,就是方法和变量在继承时的覆盖和隐藏问题,这些概念性的东西看似无聊,但是在面试或者是SCJP认证题中围绕这些是会经常碰到的,所以这里来讨论下

首先我们来看几个概念

类变量:又叫静态变量,这种变量属于类,通过类名就可以访问类变量。

实例变量:属于类的实例,即对象,通过对象可以访问实例变量,但是不能通过类名访问实例变量。

静态方法:通过类名访问。

实例方法:对象访问,不能通过类名访问。

隐藏 :child隐藏了parent的变量和方法,那么,child不能访问parent被隐藏的变量或者方法,但是,将B转换成A中,可以访问A被隐藏的变量或者方法

覆盖 :child覆盖了parent的变量或者方法,那么,child不能访问parent被覆盖的变量或者方法,将child转换成parent后同样不能访问parent被覆盖的变量或者方法

首先看一下JAVA中方法和变量在继承时的覆盖和隐藏规则

1.父类的实例变量和静态变量能被子类的同名变量隐藏

2.父类的静态方法被子类的同名静态方法隐藏

3.父类的实例方法被子类的同名实例变量覆盖

      作为通用的规则:覆盖实例方法时,新方法的访问控制不能比原来的方法更严格,但可以更松。

      1.在超类中被声明为公有的实例方法,在子类中也必须是公有的;

      2.在超类中被声明为保护的实例方法,在子类中可以是保护的或公有的,但不能私有的。

      3.在超类中默认的实例方法,在子类中其访问控制可以更严格。

      4.在超类中被声明为私有的实例方法根本不能继承,也不能被覆盖。

      子类覆盖父类的实例方法,必须有同样的(参数列表、参数名、参数返回类型),否则编译不能通过。

      子类覆盖父类的实例方法,在jdk1.5后,参数返回类可以是父类方法返回类的子类

      子类的静态方法不能隐藏同名的父类实例方法

       java与C++一样,继承的方法具有多态性

 

还有几点需要注意的是

1、不能用子类的静态方法隐藏 父类中同样标示(也就是返回值 名字 参数都一样)的实例方法

2、不能用子类的实例方法覆盖 父类中同样标示的静态方法

3、变量只会被隐藏 不会被覆盖 ,无论他是实例变量还是静态变量,而且,子类的静态变量可以隐藏 父类的实例变量,子类的实例变量可以隐藏 父类的静态变量

4、最终方法(带关键字final的方法)不能被覆盖。

 

O(∩_∩)O哈哈~ 是不是有点儿绕口,没关系 我们看一个实例

创建两个父子类关系的类

  1. //父类  
  2. class Parent  
  3. {  
  4.     public static String kind="javastudy.extendsstudy.parent";  
  5.     public static int age=50;  
  6.     public String name="Parent";  
  7.   
  8.     //静态方法,返回包名  
  9.     public static String getKind()  
  10.     {  
  11.         System.out.println("parent的getKind()方法被调用了");  
  12.         return kind;  
  13.     }  
  14.   
  15.     //静态方法,返回年龄  
  16.     public static int getAge()  
  17.     {  
  18.         System.out.println("Parent的getAge()方法被调用了");  
  19.         return age;  
  20.     }  
  21.   
  22.     //实例方法,返回姓名  
  23.     public String getName()  
  24.     {  
  25.         System.out.println("Parent的getName()方法被调用了");  
  26.         return this.name;  
  27.     }  
  28.   
  29. }  
  30.   
  31.   
  32. //子类  
  33. class Child extends Parent  
  34. {  
  35.     public static String kind="javastudy.extendsstudy.child";  
  36.     public int age=25;  
  37.     public String name="child";  
  38.   
  39.     //隐藏父类静态方法  
  40.     public static String getKind()  
  41.     {  
  42.         System.out.println("child的getkind()方法被调用了");  
  43.         return kind;  
  44.     }  
  45.       
  46.     //获取父类包名  
  47.     public static String getParentKind()  
  48.     {  
  49.         return Parent.kind;  
  50.     }  
  51.       
  52.     //覆盖父类实例方法  
  53.     public String getName()  
  54.     {  
  55.         System.out.println("child的getName()被调用了");  
  56.         return this.name;  
  57.     }  
  58.       
  59.     //获取父类名称  
  60.     public String getParentName()  
  61.     {  
  62.         return super.name;  
  63.     }  
  64.     /* 
  65.      *错误,实例方法不能覆盖父类的静态方法 
  66.     public int getAge() 
  67.     { 
  68.         return this.age; 
  69.     } 
  70.     */  
  71. }  
 

 然后测试下

  1. class Test   
  2. {  
  3.     public static void main(String[] args)   
  4.     {  
  5.         Child child=new Child();  
  6.         System.out.printf("子类名称:%s,年龄:%d,包名:%s%n",child.name,child.age,child.kind);  
  7.         //输出:子类名称:child,年龄:25,包:javastudy.extendsstudy.child  
  8.   
  9.         //把child转换成parent对象  
  10.         Parent parent=child;  
  11.   
  12.         System.out.printf("转换后的名称:%s,年龄:%d,包名:%s%n",parent.name,parent.age,parent.kind);  
  13.         //输出:转换后的名称:Parent,年龄:50,包:javastudy.extendsstudy.parent  
  14.   
  15.         System.out.printf("子类访问父类被隐藏的实例变量name:%s%n",child.getParentName());  
  16.         //输出:子类访问父类被隐藏的实例变量name:Parent  
  17.           
  18.         System.out.printf("子类访问父类被隐藏的静态变量kind:%s",child.getParentKind());  
  19.         //输出:子类访问父类被隐藏的静态变量kind:javastudy.extendsstudy.parent  
  20.   
  21.         child.getName();  
  22.         //输出:child的getName()被调用了  
  23.   
  24.         //**************注意看这个方法,返回的还是子类的getName  
  25.         parent.getName();  
  26.         //输出:child的getName()被调用了  
  27.   
  28.         child.getKind();  
  29.         //输出:child的getkind()方法被调用了  
  30.   
  31.         parent.getKind();  
  32.         //输出:parent的getKind()方法被调用了  
  33.     }  
  34. }  

 好了,看了结果后总结下吧

1.同名的实例方法被覆盖 ,同名的静态方法被隐藏 ,child类的getName实例方法覆盖 了parent的getName实例方法,chind的getKind方法隐藏 了parent类的getKind方法

2.隐藏 和覆盖 的区别在于,子类对象转换成父类对象后,能够访问父类被隐藏 的变量和方法,而不能访问父类被覆盖 的方法

3.如果需要访问父类被隐藏 的实例变量,加上super就好了,比如访问父类的name,写上super.name就好了

4.子类若要访问父类种被隐藏的类变量,则需要父类的名字加“.”来访问。比如:parent.name

本文不是教会大家重写父类变量的,而是重点说明方法和变量的隐藏和覆盖,这些个小知识点虽然在做项目的时候不怎么会用到,但是一定要记住,不然的话很多错误会感到莫名其妙,还有就是SCJP的题库里这类题大大存在,所以本人觉得这些细小的知识还是记住为好。

转载于:https://www.cnblogs.com/lubocsu/p/5101815.html

你可能感兴趣的文章
【SVM】libsvm-python
查看>>
Jmeter接口压力测试,Java.net.BindException: Address already in use: connect
查看>>
Leetcode Balanced Binary Tree
查看>>
Leetcode 92. Reverse Linked List II
查看>>
九.python面向对象(双下方法内置方法)
查看>>
go:channel(未完)
查看>>
[JS]递归对象或数组
查看>>
LeetCode(17) - Letter Combinations of a Phone Number
查看>>
Linux查找命令对比(find、locate、whereis、which、type、grep)
查看>>
路由器外接硬盘做nas可行吗?
查看>>
python:从迭代器,到生成器,再到协程的示例代码
查看>>
Java多线程系列——原子类的实现(CAS算法)
查看>>
在Ubuntu下配置Apache多域名服务器
查看>>
多线程《三》进程与线程的区别
查看>>
linux sed命令
查看>>
html标签的嵌套规则
查看>>
[Source] Machine Learning Gathering/Surveys
查看>>
HTML <select> 标签
查看>>
类加载机制
查看>>
tju 1782. The jackpot
查看>>