继承是类与类之间的继承,是一种is a 的关系(继承的知足条件)函数
继承的类叫子类 / 派生类,被继承的叫父类 / 基类优化
Java中的继承也是单继承this
经过extends关键字来实现继承关系的spa
class 子类名 extends 父类名 {……}code
class Fu {…} class Sub extends Fu {…}
〈1.优化代码。减小代码的重复使用。对象
〈2.复用代码。子类若是继承父类,就拥有了父类的方法和属性,子类能够复用父类的方法和属性blog
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. 子类不可以继承在同一个包
为何会调用父类的构造方法?
子类在建立对象的时候先初始化父类的变量
在添加变量的时候,不加权限修饰符,默认是friendly修饰,而不是public
访问权限 |
类 |
包 |
子类 |
其它包 |
public |
∨ |
∨ |
∨ |
∨ |
protect |
∨ |
∨ |
∨ |
× |
default |
∨ |
∨ |
× |
× |
private |
∨ |
× |
× |
× |
指向父类对象的引用空间
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仍是李四 } }
1.在子类的构造方法中调用父类的无参构造方法时用super语句,必须放在第一句
二、super只能出如今子类的方法中,经常使用来调用父类的构造方法
三、super和this不可以同时调用构造方法。由于两个在子类调用时构造方法时,都须要放在第一位,形成冲突
1.对象不同:
this:当前方法的调用对象。
super:表示父类对象的引用空间。
2.条件不一致:
super: 只能在继承的条件下使用。
this: 没有限制。
3.调用的构造方法不同:
super :调用父类的构造方法
this : 调用本类构造方法
当父类的方法知足不了子类的实现,这个时候就经过复写来实现父类的行为,来保持本身特性
可是int类型必须保持一致
class Animl { public int run() { return 100; } } class Cat extends Animl { // 重写父类的方法 public int run() { //父类的是返回值int类型,子类中的是double类型,也会报错:double与int类型不兼容 return 100; } }
6.和方法的重载加以区分:重载时方法名同样,参数列表的个数、类型或顺序不同
7子类的异常类型要小于或等于父类的异常类型
先初始化父类的属性和方法,而后才初始化子类的属性和方法
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 表示这个对象是这个类建立的 } }
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基本数据类型变量名
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 来修饰的方法不能有方法体。
2.类中有抽象方法,类必须用abstract 来修饰
3.非抽象的类,继承了这个抽象类,非抽象类中必 须重写父类全部的抽象方法。
4.抽象类中能够有非抽象的方法,也能够没有
5.抽象类中能够存在构造方法。-->做用是让子类能 够初始化父类中的变量和方法。
6.抽象类不可以建立对象。
缘由:若是建立对象,对象就能够调用到抽象方法,可是调用的抽象方法没有意义。
在描述一个事物的时候,发现这个事物确实存在某种行为,可是这种行为又不具体,声明一个没有实现的行为,这种行为就叫抽象的行为
1.不能和private。
2.不能和static使用。
3.不能和final使用
在Java中很常见
用interface关键字来表示接口
结构:interface 接口名();
结构:
class 类 implements 接口名1,接口名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(); }
}
1.接口是一个特殊的类,是能够定义属性和方法。
2.成员变量默认是用final修饰的 : public static final 其实是一个常量,必须初始化一次并且只能初始化一次
3.方法都是抽象的: abstract public
4.接口中不能有建立对象、构造方法和普通方法,由于默认是由abstract修饰的类,方法中不能带有方法体的,不带主体的普通方法、构造方法是没有意义的,全部不能使用。
5.接口是给类去实现的,非抽象类实现接口时,必须把接口中的全部方法都实现了。