目录
1.概念:
2.使用:
3.super关键字
4.子类构造方法
5.super和this关键字
6.初始化时代码块的执行顺序
7.继承的方式
8.final关键字
1.概念:
是面向对象程序设计代码可以重复使用的重要手段,允许程序员在保持原有类特性的基础上进行扩展,增加新功能,产生新类成为派生类/子类;被继承的类叫父类/基类
那么为什么会有继承呢?
假如我们要定义好多的类,都是描述动物的类,这些类有共同的特点,成员变量都含有动物的名字,年龄;如果每写一个类都要这样定义的话未免有点过于麻烦了;我们可以定义一个父类,包含年龄,名字;以后定义的子类只要继承它就好了;
继承解决的问题是:共性抽取,实现代码复用,然后实现多态。
2.使用:
继承要使用关键字:extends
public class Animal{
String name;
int age;
public void eat(){
System.out.println(name + "正在吃饭");
}
public void sleep(){
System.out.println(name + "正在睡觉");
}
}
// Dog.java
//Dog继承Animal
public class Dog extends Animal{
//此时Dog中也有 name;age成员变量,但未显示;
void bark(){
System.out.println(name + "汪汪汪~~~");
}
}
注意:继承后的子类必须要有自己的成员变量或者方法,不然与父类一模一样就没必要继承了。
3.super关键字
父类和子类中可能出相同的成员变量或方法,如果想在子类中访问父类成员变量是很难的,java中提供了static关键字;
作用:在子类方法中访问父类成员变量或方法
注意:只能在静态方法中使用,在子类方法中访问父类变量和方法
class testA{
public int a = 100;
public int b = 200;
}
class testB extends testA{
public int a = 10;
public int b = 20;
}
public class Test {
public static void main(String[] args) {
testB testB = new testB();
System.out.println(testB.a);
System.out.println(testB.b);
}
}
输出结果 10 20;
子类继承父类之后,在实例化子类对象的时候要想帮助父类进行构造,初始化父类成员
规则:如果子类与父类有同名的成员变量,优先访问子类成员变量,若子类没有再访问父类,如果父类再没有就报错。
那么如何访问父类中的成员变量呢?
可以在子类中再定义一个方法,用关键字super,因为super只能在子类定义的方法中访问父类变量
class testA{
public int a = 100;
public int b = 200;
}
class testB extends testA{
public int a=10;
public int b=20;
public void method(){
System.out.println(super.a+" "+super.b);
}
}
public class Test {
public static void main(String[] args) {
testB testB = new testB();
System.out.print(testB.a +" ");
System.out.println(testB.b);
testB.method();
}
}
结果:10 20
100 200
访问成员方法也是一个道理,但是如果方法的重载,根据参数列表的不同可以不同访问,但是如果构成方法的重写,就要通过super关键字来访问了
class testA{
public void methodA(){
System.out.println("testA:methodA()");
}
public void methodB(){
System.out.println("testA:methodB()");
}
}
class testB extends testA{
int a = 10;
public void methodA(int a){
System.out.println(this.a);
}
public void methodB(){
System.out.println("testB:methodB()");
}
public void methodC(){
super.methodB();
}
}
public class Test {
public static void main(String[] args) {
testB test = new testB();
test.methodA();
test.methodA(10);
test.methodB();
test.methodC();
}
}
结果:
testA:methodA()
10
testB:methodB()
testA:methodB()
4.子类构造方法
子类对象构造时,先执行基类方法在调用子类构造方法
class Base{
public Base(){
System.out.println("父类构造方法");
}
}
class Drev extends Base{
public Drev(){
System.out.println("子类构造方法");
}
}
public class Tets {
public static void main(String[] args) {
Drev drev = new Drev();
}
}
结果:
父类构造方法
子类构造方法
说明:在子类方法中,并没有写构造父类方法的代码,为什么会构造子类对象的时候会先调用父类构造代码呢?
因为子类中有两部分代码,一种是继承父类的,还有一种是自己的构造代码,在构造对象时会先调用父类构造方法,将子类中从父类那继承的成员构造完整,再调用子类自己的构造方法将子类的成员初始化完整;
注意:
1.若父类显式定义无参时或者默认构造方法时,子类构造方法中第一行会默认有super(),随后调用子类构造方法;
2.若父类构造方法有参数,此时用户需要为子类显示构造方法,并在子类构造方法中选择合适的父类构造方法调用
3.在子类构造方法中,super()调用父类构造方法时,super()必须是子类构造方法的第一条语句。
4.super()在子类构造方法中只能出现一次,而且不能和this同时出现
5.super和this关键字
super和this都可在成员方法中访问成员变量或成员方法,但有什么区别呢?
class Base1{
public int a = 1;
public int b = 2;
}
class Der extends Base1{
public int c = 3;
public int a = 10;
public void test(){
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(super.a);
System.out.println(this.a);
}
}
public class Test2 {
public static void main(String[] args) {
Der der = new Der();
der.test();
}
}
结果:
10
2
3
1
10
这个例子可以清晰看到:当子类成员与父类成员有相同名字的时候,会优先访问子类成员变量,如果要可以访问父类成员,需要加上super,访问子类需要用this
相同点:
1.都是关键字
2.都只能在非静态的类成员方法中使用,访问非静态成员方法和字段
3.在构造方法调用时,只能是构造方法的第一条语句,不能同时存在
不同点:
1.this是对当前对象的引用,super是对从父类继承下来的成员的引用
2.非静态成员方法中,super是对父类成员方法的引用,this是对本类成员方法的引用
3.this和super不能同时在构造方法中出现
4.构造方法中一定存在super,不写也有。this不写则没有
6.初始化时代码块的执行顺序
1.实例化代码块和静态代码块,在没有继承时的顺序如下
class Person{
public String name;
public int age;
public Person(String name,int age){
this.age=age;
this.name=name;
System.out.println("构造方法执行");
}
//实例化代码块
{
System.out.println("实例化代码块");
}
//静态代码块
static {
System.out.println("静态代码块");
}
}
public class Test1 {
public static void main(String[] args) {
Person person = new Person("小明",12);
}
}
结果:
静态代码块
实例化代码块
构造方法执行
在没有继承关系时,静态代码块>实例化代码块>构造方法
1.静态代码块只执行一次,在类加载的时候进行。
2.只有对象创建的时候执行实例化代码,实例化代码完成后会调用构造函数
在继承时,静态代码与实例化代码的关系?
class Person{
public String name;
public int age;
public Person(String name,int age){
this.age=age;
this.name=name;
System.out.println("构造方法执行");
}
//实例化代码块
{
System.out.println("实例化代码块");
}
//静态代码块
static {
System.out.println("静态代码块");
}
}
class Student extends Person{
public Student(String name,int age){
super(name,age);
System.out.println("Student的构造方法");
}
{
System.out.println("Student的实例化代码");
}
static {
System.out.println("Studentd的静态代码");
}
}
public class Test1 {
public static void main(String[] args) {
Student student = new Student("小红",15);
}
}
结果
静态代码块
Studentd的静态代码
实例化代码块
构造方法执行
Student的实例化代码
Student的构造方法
规则:
1.父类静态代码块先于子类静态代码块执行,且最早执行
2.父类实例化代码块和它的构造方法紧接着执行
3.然后是子类的实例化代码和它的构造方法
4.第二次实例化对象的时候,静态代码块不会再执行
7.继承的方式
继承有多层继承,单继承,不同类继承同一个类
8.final关键字
final可以修饰成员变量,成员方法或者类
1.修饰成员变量或者字段,表示常量(不能被修改)
final int a = 10;
a = 20;//编译出错
2.修饰类表示不能被继承
final public class Animal {
...
}
public class Bird extends Animal {
...
} /
/ 编译出错
Error:(3, 27) java: 无法从最终com.bit.Animal进行继
平时用的String类型就是fianl修饰的,不能被修改
3.修饰方法表示不能被重写