对象的继承
1)继承是面向类的对象,也就是class修饰的对象。只有class修饰的对象才能被继承或者继承别人。单独的方法和变量是不能直接被继承和继承别人的哦,都是以class为载体的。
而一个class对象只能继承一个其他的class对象,不能继承两个。但一个class对象可以被多个class对象继承。
这个继承和被继承要分清楚哦!
被继承的叫父类,继承别人的人叫子类。
子类通过extends进行继承父类,具体实例如下:
package com.see;
public class TryFirst {
}
class TrySecond extends TryFirst{
}
例子里面的TrySecond就是子类,通过extends继承了父类TryFirst,顺便一提,例子里面的package 指的是文件夹,意思就是我这个class文件保存在com文件夹里面的see文件夹里面,对该class文件点击右键选择properties,你会发现:
图片上可以看见两个地址,一个是path(项目地址) 一个是location(本地地址)
这个class文件的path地址确实就是/Try/src/com/see/TryFirst.java;而本地地址(location)我们也能在本地中找到,具体如下图:
通过这个我们已经知道啦,package指的其实就是文件夹,指的是在项目src之后的文件夹路径。顺便一提,package的写法,也就是文件夹的命名,都必须是小写字母开头,不能用大写啦!多个文件夹嵌套的话,就用“.”号隔开,就像图片上那样。
还有要注意的一点是,一个class文件里面可以有多个class对象哦!比如例子上的子类和父类两个对象。不要以为一个class文件只能有一个class类哦!不过一个class文件里面只能有一个class类被public修饰,如果有两个就会报错啦!
2)成员变量的隐藏和方法的重写
package com.see;
class farther {
public void way() {
String str = "farther";
System.out.println(str);
}
}
class son extends farther {
public void way() {
String str = "son";
System.out.println(str);
}
}
public class TryExtends {
public static void main(String[] args) {
farther faa = new son();
faa.way();
}
}
例子的输出结果是“son”,它把farther的成员变量str给隐藏以来了,也把farther的方法way给重写了,结果全是子类的。
关键点就是子类有没有重复做父类的事,如果有,那父类就会被隐藏被重写,如果没有,比如子类是这么写的:
class son extends farther {
}
里面空空的,啥也没写,那么就不会造成父类成员变量的隐藏和方法的重写。
那么方法的重写需要注意的点:
a.方法的参数类型和个数一致
b.方法返回值类型一致
c.重写不得降低父类方法的访问权限(什么是访问权限下面会讲到)
3)用super来调用隐藏变量和调用重写方法
当父类的方法和变量被隐藏和重写的时候,可以在子类中通过super来进行调用:
class farther {
public void way() {
String str = "farther";
System.out.println(str);
}
}
class son extends farther {
public void way() {
String str = "son";
System.out.println(str);
super.way();
}
}
public class TryExtends {
public static void main(String[] args) {
farther faa = new son();
faa.way();
}
}
输出结果既有son也有father,需要注意的是,super只能调用相应类的方法然后间接的调用其的变量,不能直接调用变量的哦!按照我上面的例子也就是不能直接调用父类的str:super.str;
4)通过super调用父类的构造方法
构造方法有,有参构造方法和无参构造方法两种,无参的构造方法是在实例化的时候被调用,之前也谈过通过this来调用有参构造方法,但是这得写在无参构造方法里的,而super调用的构造方法不是自己的有参构造方法,而是父类的有参构造方法:
class farther {
farther(){
System.out.println("父类无参构造方法");
}
farther(int a){
System.out.println("父类有参构造方法"+a);
}
}
class son extends farther {
son(){
this(0);
System.out.println("子类无参构造方法");
}
son(int a){
super(1);
System.out.println("子类有参构造方法"+a);
}
}
public class TryExtends {
public static void main(String[] args) {
farther faa = new son();
}
}
输出结果是:
父类有参构造方法1
子类有参构造方法0
子类无参构造方法
我们来缕一缕哈,
在存在super(1);
的情况下:
首先看main方法里,实例化的其实是对象上转型,什么意思呢,farther faa = new son();
就是实例化时,是父类声明farther
实例化的却不是父类,而是子类new son()
,这样的实例化就叫上转型实例化,那么,在存在super(1);
的情况下,就会执行子类的无参构造方法,该方法里用了this(0)
,不会执行父类的无参构造方法,因为用了super(1);
,调用了父类的有参构造方法。具体步骤如下:
调用了子类的有参构造方法,而在子类的有参构造方法里,又调用了父类的有参构造方法super(1);
。
在父类的有参方法中,没有再调用什么方法了,只有输出,所以首先输出的是:父类有参构造方法1
之后返回来,父类有参方法调用完毕了,子类的有参方法继续往下执行代码,所以就着输出的是子类有参构造方法0
,
到这里,子类的有参方法就执行完了,这个时候子类的无参方法会继续往下执行带来,这个时候就会输出子类无参构造方法
,
然后代码就执行完毕了,没有调用到父类的无参构造方法,因为实例化的是子类farther faa = new son();
要想调用父类的无参构造方法,只要改成farther faa = new farther ();
就可以了
当不存在super(1);
的时候,上转型实例化时,会先执行父类的无参构造方法,然后再执行子类的无参构造方法。
注意点
a.父类有参的构造方法只能在子类的有参构造方法中通过super来调用,而且必须写在第一行,不能写在其它地方。
b.this(参数)是调用当前类(子类)的有参构造方法,而super是调用父类的有参构造方法,别弄混了。
c.当存在super(1);
调用父类的有参构造方法时,程序就不会再调用父类的无参构造方法了。
访问权限
对象或者变量的访问权限有:
public(公共的)、protected(受保护的)、友好的(默认的)、private(私有的)
举个例子说明吧:
通过这个例子我们可以看见,一个class文件里,public 、protected以及友好的的参数都能被其他class类所调用,但private私有的,只能在当前class内被使用,哪怕是同一个class文件里面的其它class类都不能调用,调用的话,就会报错。
即,private(私有的)只能在当前class类内使用
在同一个文件夹下,不同的两个class文件,我们还是可以看见,public 、protected以及友好的的参数都可以被调用。
通过上面那个图片例子,我们可以看出,两个class文件不在同一个文件夹里,在这种情况下,我们可以看出TrySecond(子类)继承了TryFirst(父类)
在子类中,未实例化任何类的时候,就可以直接调用父类的public和protected修饰的变量(图中的i变量和j变量),实例化子类后可以调用的只有被public和protected修饰的变量,默认的友善变量©不可以被调用。而在实例化父类的时候,protected和友好的变量都不可以背调用,看途中的b1、b2就知道了。
即,protected能在子类中调用(需实例化的是子类或者直接调用父类的变量)而默认友好的变量不可以在子类中背调用(不管实例化哪个类或者不实例化都不可以)
顺便提一下上面图片中出现的import,这是迎来引用的,因为两个class文件不在同一个文件夹里,互相都找不到对方,这个时候,谁要找谁(引用)的话,就需要用到import来指明方向了,而TrySecond需要继承TryFirst,这个时候就需要在TrySecond中引用(import)TryFirst了。
上图,最后一个例子,通过这个例子我们可以看出TryFirst类和TrySecond类不在同一个文件夹里,这个时候,我们可以在TrySecond中调用TryFirst定义的public修饰的变量a,但是TrySecond不可以调用在TryFirst定义的protected修饰的变量b。
通过以上几个例子,我们可以找到各个修饰符所含有的访问权限是:
权限级别分别是:public(公共的)>protected(受保护的)>友好的(默认的)>private(私有的)
刚刚说的是变量,其实方法被public(公共的)、protected(受保护的)、友好的(默认的)、private(私有的)所修饰的时候也是一样的:
公有的方法可以被任何的其它类访问;
受保护的方法可以背同一个文件夹下的其它类访问,也可以被子类访问(哪怕不是在同一个文件夹内);
友好默认的方法只能被同一个文件夹下的类访问;
私有的方法只能在当前class文件内被访问。
----------END