- 继承
- super关键字
- 重写
- final关键字
- 抽象类/abstract关键字
- 接口
一.继承
继承是类与类之间的继承,是一种is a 的关系(继承的满足条件)
继承的类叫子类 / 派生类,被继承的叫父类 / 基类
Java中的继承也是单继承
1.extends关键字
通过extends关键字来实现继承关系的
class 子类名 extends 父类名 {……}
class Fu {…} class Sub extends Fu {…}
2.好处
〈1.优化代码。减少代码的重复使用。
〈2.复用代码。子类如果继承父类,就拥有了父类的方法和属性,子类可以复用父类的方法和属性
3.继承的使用注意点
1.不要为了继承而继承。两个类必须存在is a 的关系
2.子类不允许继承父类的构造方法
3.子类继承了父类,在调用自己的构造方法时,如果父类没有写有参的构造方法,系统会默认优先调用父类的构造方法
如果父类中写了有参的构造方法,系统就不会调用无参的构造方法,则子类不能调用到父类的构造方法导致报错
a) 解决办法:
1. 方案一.在父类中添加无参构造方法让子类调用
2.方案二.在子类的构造方法里第一个语句添加super关键字及传入参数
//—>常犯错题1******************************* class Fu { String name; String color; public Fu(String name, String color) { //1.继承中不能调用父类的构造方法 this.name = name; this.color = color; } public Fu() { //在父类中添加无参构造方法让子类调用 } } class Sub extends Fu { int age; public Sub(int age, String name, String color) { super(name,color); // 使用super关键字及传入参数,必须放在第一语句 this.age = age; //this调用自己的构造方法 super();调用父类的构造方法 this.name = name; this.color = color; } }
4. 如果用private修饰的属性和方法不能继承
5. 子类不能够继承在同一个包
为什么会调用父类的构造方法?
子类在创建对象的时候先初始化父类的变量
4.权限修饰符
在添加变量的时候,不加权限修饰符,默认是friendly修饰,而不是public
访问权限 |
类 |
包 |
子类 |
其它包 |
public |
∨ |
∨ |
∨ |
∨ |
protect |
∨ |
∨ |
∨ |
× |
default |
∨ |
∨ |
× |
× |
private |
∨ |
× |
× |
× |
5.Super关键字
指向父类对象的引用空间
super关键字:用来初始化父类的属性和方法
1.super关键字的使用:
1.当子类和父类的成员变量在重写同名的时候,可以通过super来访问父类的成员变量
2.super可以调用父类的构造方法
//—>常犯错题******************************* class Fu { String name = "张三"; String color; public Fu(String name, String color) { this.name = name; this.color = color; } } class Zi extends Fu { int age; public Zi(int age, String name, String color) { super(name,color); this.age = age; } public void run() { //System.out.println(name + "调用了方法"); //默认在name前面隐式性的加了this关键字,调用当前自己的成员变量 System.out.println(super.name + "调用了方法"); //****使用super关键字,优先调用父类的属性,然后子类创建的对象,同时给参数赋值会覆盖父类中name的值,所以调用super还是李四 } }
2.super使用注意点:
1.在子类的构造方法中调用父类的无参构造方法时用super语句,必须放在第一句
2、super只能出现在子类的方法中,常用来调用父类的构造方法
3、super和this不能够同时调用构造方法。因为两个在子类调用时构造方法时,都需要放在第一位,造成冲突
3.super和this的区别:
1.对象不一样:
this:当前方法的调用对象。
super:表示父类对象的引用空间。
2.条件不一致:
super: 只能在继承的条件下使用。
this: 没有限制。
3.调用的构造方法不一样:
super :调用父类的构造方法
this : 调用本类构造方法
二.方法的重写
1.作用:
当父类的方法满足不了子类的实现,这个时候就通过复写来实现父类的行为,来保持自己特性
2.注意点:
- 有继承关系
- 子类和父类的方法名、形式参数要一致
- 子类重写父类的方法,会优先调用子类的方法,有可能导致父类的方法不能使用???
- 子类的权限修饰符必须要大于或等于父类的权限修饰符
- 子类的返回值类型必须小于或等于父类的返回值类型
但是int类型必须保持一致
class Animl { public int run() { return 100; } } class Cat extends Animl { // 重写父类的方法 public int run() { //父类的是返回值int类型,子类中的是double类型,也会报错:double与int类型不兼容 return 100; } }
6.和方法的重载加以区分:重载时方法名一样,参数列表的个数、类型或顺序不一样
7子类的异常类型要小于或等于父类的异常类型
3继承中的初始化顺序:
先初始化父类的属性和方法,然后才初始化子类的属性和方法
4.Instanceof(实例类型)关键字的作用:
1. 判断某一个对象是否由这个类创建
2. 使用前提:继承关系
语法:对象 instanceof 类名;
//在Student类继承于Person类 class Demo { public static void main(String[] args) { //判断p对象是否属于Person类 Person p = new Person(); boolean b1 = p instanceof Person; System.out.println(b1); //true 表示这个对象是这个类创建的 Student s = new Student(); boolean b2 = s instanceof Person; //必须满足继承Person类 System.out.println(b2); //true 表示这个对象是这个类创建的 } }
5.final关键字
final关键字作为修饰符,可理解为“最终的”意思
1.final修饰的类型:
- 类:修饰的类将不能被继承
- 方法:修饰的方法将不允许重写(覆盖)
class Yuan{ int r; public final static double pi = 3.14; //final修饰的属性时可直接赋值,而且只能赋值一次 public Yuan(int r) { this.r = r; } public void area() { //final修饰的属性不能在构造方法中初始化 System.out.println("圆的面积是:" + r*r*pi); } } class Demo{ //常见错误点********** public static void main(String[] args) { final Yuan yu = new Yuan(10); yu.area(); //参数列表中的变量是都是局部变量,所以在两个方法中的值是互不影响的 test(yu); } public static void test(Yuan you) { you = new Yuan(20); //******创建了一个新的地址,所以可以改变值,这儿的形参名可以和上面主函数传递进来的参数不一样,两个都是指向的是不同一个内存空间 you.area(); } }
final的内存分析图:
3. 属性:用final修饰的属性必须初始化而且只能初始化一次
可在添加属性直接赋值,在没有添加static修饰的时候,也可在构造方法或主方法中赋值,但是不能再普通方法中给final初始化
4.变量:变量的值必须赋值一次而且只能赋值一次,赋值过后的变量就变成了常量(常量:不能改变的量)。不管是修饰基本数据类型还是引用数据类型,第一次的结果为最终的结果,修改值将会报错
为什么只能初始化一次?在没有final修饰的属性中,即使你没给它赋值,系统会给它一个隐式的默认值,但是用final修饰的时候,没有给它初始化的话是没有值的,所有会报错
Final修饰常量语法:public final static基本数据类型变量名
2.两个值的交换Demo :
public static void main(String[] args) { int a = 10; int b = 20; //定义一个方法交换,基本数据类型之间的赋值,实际是直接把值赋给变量,并没有作交换 change(a, b); System.out.println("a = " + a + "," + "b = " + b); //定义一个方法交换,引用数据类型之间的赋值,实际是地址之间的交换来达到目的 int[] arr = {10, 20}; changeArr(arr); System.out.println("a = " + arr[0] + "," + "b = " + arr[1]); } public static void change(int a, int b) { //值没有交换 int tmp = a; a = b; b = tmp; } public static void changeArr(int[] arr) { //交换了 int tmp = arr[0]; arr[0] = arr[1]; arr[1] = tmp; }
如果形式参数是基本数据类型,传递的就是值
如果形式参数是引用类型,传递的参数是地址
交换值的内存分析图
三.抽象类
用关键字abstract
背景:在重写父类时,可以不写父类的方法,但是有可能会有问题,这就可以用abstract来强制性让子类重写父类的方法
抽象类:一个类如果被abstract修饰那么这个类就叫抽象类。
1.如果abstract修饰方法,那么这个方法就叫抽象的方法
2.如果abstract修饰类,那么这个类叫抽象类。
方法体:方法中大括号的内容就是方法体
abstract class Graphies { int c; int k; abstract public void area(); } //圆形类 class Roundness extends Graphies { int r; final static double PI = 3.14; //常量的命名规则:首字母大写,多个单词用下划线隔开 public void area() { //必须重写父类的抽象方法,而且方法名、返回值类型必须相同 System.out.println("这个圆的面积是:" + PI * r * r); } public Roundness(int r) { //PI = 3.14; //如果final修饰的变量加了static修饰,则初始化变量只能在命名的就给它赋值 this.r = r; } } class Demo { public static void main(String[] args) { //创建圆形类调用方法 Roundness r1 = new Roundness(10); r1.area(); } }
1.abstract关键字的使用:
1. 用abstract 来修饰的方法不能有方法体。
2.类中有抽象方法,类必须用abstract 来修饰
3.非抽象的类,继承了这个抽象类,非抽象类中必 须重写父类所有的抽象方法。
4.抽象类中可以有非抽象的方法,也可以没有
5.抽象类中可以存在构造方法。-->作用是让子类能 够初始化父类中的变量和方法。
6.抽象类不能够创建对象。
原因:如果创建对象,对象就可以调用到抽象方法,但是调用的抽象方法没有意义。
2.abstract关键字的使用场景:
在描述一个事物的时候,发现这个事物确实存在某种行为,但是这种行为又不具体,声明一个没有实现的行为,这种行为就叫抽象的行为
3.充abstract不能够和那些关键字连用:
1.不能和private。
2.不能和static使用。
3.不能和final使用
四.接口
在Java中很常见
1.接口定义模式:
用interface关键字来表示接口
结构:interface 接口名();
结构:
class 类 implements 接口名1,接口名2...{
}
一个类如果实现了一个接口,需要将所有的抽象方法实现
2.作用:
1. 用来扩展功能
2. 让程序解耦
3. 定义约束
// 要继承的类1 用interface关键字 interface Pin { int age = 12; //默认是由final修饰的,必须给它赋值。而且只能赋值一次 public void xie(); //默认是由abstract修饰的 } interface Ca // 要继承的类2 用interface关键字 { public void ca(); } //继承类 用implements关键字 class PinCa implements Pin, Ca //注意继承多个接口的方法,要用逗号隔开 { public void xie() { System.out.println("写字的功能"); } public void ca() { System.out.println("擦字的功能"); } } class Demo { public static void main(String[] args) { PinCa pc =new PinCa(); pc.xie(); pc.ca(); }}
3.接口的使用注意事项:
1.接口是一个特殊的类,是可以定义属性和方法。
2.成员变量默认是用final修饰的 : public static final 实际上是一个常量,必须初始化一次而且只能初始化一次
3.方法都是抽象的: abstract public
4.接口中不能有创建对象、构造方法和普通方法,因为默认是由abstract修饰的类,方法中不能带有方法体的,不带主体的普通方法、构造方法是没有意义的,所有不能使用。
5.接口是给类去实现的,非抽象类实现接口时,必须把接口中的所有方法都实现了。