目录
继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为
类的继承格式
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,如:
public class Person(父类 ){
}
public class Male(子类) extends Person(父类) {
}
public class Female(子类) extends Person(父类) {
}
以上子类Male和Female继承了父类 Person
继承的特性
子类拥有父类非 private 的属性、方法。
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。
Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
继承类型
单继承
多重继承
不同类继承同一个类
多继承
需要注意的是 Java 中 extends 关键字不支持多继承,但支持多重继承。
继承关键字
extends关键字
在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
public class Person {
private String nickname;
private int gender;
private int age;
public Person(String nickname, int gender, int age){
this.nickname = nickname;
this.gender = gender;
this.age = age;
}
public void eat() { //吃东西方法的具体实现 }
}
public class Male extends Person{
}
public class Female extends Person {
}
implements关键字
使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。
public Person A {
public void eat();
public void drink();
}
public Person B {
public void run();
}
public class C implements A,B {
}
super 与 this 关键字
super关键字:可以通过使用super关键字来实现对父类成员的访问,用来引用或调用当前对象的父类
注意:super在调用父类构造方法的时候只能放在第一行
public class Male extends Person {
public Male() {
System.out.println("Male类的无参构造方法");
}
public Male(String nickname, int gender, int age) {
// super 调用父类构造方法的时候 注意:只能放在第一行
super(nickname, gender, age);
System.out.println("Male类的有参构造方法");
}
}
this关键字:调用本类里的构造方法
this:在构造方法中调用其他构造方法 只能放在第一行
注意:使用this调用构造方法的时候 不允许相互调用 造成死循环
public class Person08 {
private final static int defaultCapacity = 10;
private int[] capacity;
public Person08() {
// capacity = new int[defaultCapacity];
// this:在构造方法中调用其他构造方法 只能放在第一行
// 注意:使用this调用构造方法的时候 不允许相互调用 造成死循环
this(new int[defaultCapacity]);
// this(10,20);
}
public Person08(int[] capacity) {
super();
this.capacity = capacity;
}
public int[] getCapacity() {
return capacity;
}
public void setCapacity(int[] capacity) {
this.capacity = capacity;
}
}
final 关键字
- final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
- final 含义为 “最终的”
public abstract class Person {
public abstract void eat();
// final是最终的方法 子类里不能再被重写
public final void work() {
System.out.println("治国安邦平天下");
}
}
- 使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写
final修饰的类不能被继承
public final class Person {
public final void work() {
System.out.println("治国安邦平天下");
}
}
public class Male extends Person { }
final修饰的方法不能被重写
public class Male extends Person {
@Override
public void eat() {
System.out.println("奔跑吧兄弟");
}
// - Cannot override the final method from Person
// final是最终的方法 子类里不能再被重写
// @Override
// public void work() {
// TODO Auto-generated method stub
// super.work();
// }
}
子类实例化先实例化父类
当实例化子类对象的时候,先调用父类的构造方方法
子类可以有自己的独立方法
Person父类
public class Person {
private String nickname;
private int gender;
private int age;
public Person() {
System.out.println("Person类的无参构造方法");
}
public Person(String nickname, int gender, int age) {
this.nickname = nickname;
this.gender = gender;
this.age = age;
System.out.println("Person类的有参构造方法");
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void est() {
System.out.println("吃吃吃");
}
}
Male 子类
public class Male extends Person {
public Male() {
System.out.println("Male类的无参构造方法");
}
public Male(String nickname, int gender, int age) {
super.setNickname(nickname);
super.setGender(gender);
super.setAge(age);
System.out.println("Male类的有参构造方法");
}
public void work() {
System.out.println("男人负责赚钱养家");
}
}
Female子类
public class Female extends Person {
public Female() {
System.out.println("Female类的无参构造方法");
}
public Female(String nickname, int gender, int age) {
super.setNickname(nickname);
super.setGender(gender);
super.setAge(age);
System.out.println("Female类的有参构造方法");
}
public void beauty() {
System.out.println("女人负责貌美如花");
}
}
测试类
public class PersonTest {
@Test
public void test04() {
Male male = new Male();
Female female = new Female();
male.est();
female.est();
male.work();
female.beauty();
}
}
输出结果:
Person类的无参构造方法
Male类的无参构造方法
Person类的无参构造方法
Female类的无参构造方法
吃吃吃
吃吃吃
男人负责赚钱养家
女人负责貌美如花
父类的引用指向子类的实例化对象
向上转型
数据类型是父类 实例化对象是子类
子类不能调取父类里没有的方法
public class PersonTest{
@Test
public void test05() {
Person male = new Male();
Person female = new Female();
male.est();
female.est();
// male.work();
// female.beauty();
}
}
向下转型
类型不对需要 强制转换
注意: 只有引用类型对象的真实身份为子类对象才可以转换
public class PersonTest{
@Test
public void test06() {
Male person = (Male) new Person("张三", 1, 20);
}
}
public class PersonTest{
@Test
public void test07() {
// 向上转型
Person person = new Male();
// 向下转型
Male male = (Male) person;
person.est();
male.est();
// person.work();
male.work();
((Male) person).work();
}
}
方法重写
- 当父类的方法满足不了子类需求的时候 子类可以重写父类的方法 这种表现形式称之为方法的重写
- 在 Java 中通过 Override可以重写父类的方法
- 方法重写后以子类为准
在子类中右键选择Source或者使用键盘Alt+Shift+s点击Override/lmplement Methods… 后点击回车键
勾选需要重写的方法点击ok
此时子类中自动已生成一个重写的eat方法
子类中输出自己的方法
测试
方法重载与方法重写
区别:
- 在同一个类中,参数列表不同的同名方法我们称之为方法重载
- 父类的方法满足不了子类需求,子类重写父类的方法我们称之为方法重写
- 方法重载在同一个类中 而方法重写必须存在子父类继承关系
public class InheritanceTest {
public static void main(String[] args) {
Super s = new Sub();
Goo goo = new Goo();
goo.g(s);
// 输出结果为:g(Super)..Sub.f()
// 重写看类型 重写看类型
// 眼睛是显示器 大脑是编译器
}
}
class Super{
public void f() {
System.out.println("Super.f()");
}
}
class Sub extends Super{
@Override
public void f() {
System.out.println("Sub.f()");
}
}
class Goo{
public void g(Super obj) {
System.out.println("g(Super)..");
obj.f();
}
public void g(Sub obj) {
System.out.println("g(Sub)..");
obj.f();
}
}
内部类方法的调用方式
静态成员内部类
静态内部类中写一个静态方法
public class Outer01 {
public static class Inner01 {
public static void run() {
System.out.println("奔跑吧兄弟");
}
}
}
调用静态内部类中的静态方法需要写一个测试类
public class InnerTest {
@Test
public void outer01() {
Outer01.Inner01.run();
}
}
调取输出
奔跑吧兄弟
非静态成员内部类
非静态内部类中写一个静态方法
public class Outer02 {
public class Inner {
public static void run() {
System.out.println("奔跑吧兄弟");
}
}
}
调用非静态内部类中的静态方法需要写一个测试类
public class InnerTest {
@Test
public void outer02() {
Outer02.Inner.run();
}
}
调取输出
奔跑吧兄弟
实例化非静态成员内部类
非静态内部类中写一个非静态方法
public class Outer03 {
public class Inner {
public void run() {
System.out.println("奔跑吧兄弟");
}
}
}
调用非静态内部类中的非静态方法需要写一个测试类
同时需要实例化外部类和内部类才能调取非静态内部类中的非静态方法
public class InnerTest {
@Test
public void outer03() {
// Outer03.Inner.run();
new Outer03().new Inner().run();
}
调取输出
奔跑吧兄弟
方法调用非静态成员内部类方法
在类中再写一个方法
public class Outer04 {
public class Inner {
public void run() {
System.out.println("奔跑吧兄弟");
}
}
public void innerRun() {
new Inner().run();
}
}
借助内部的方法调用内部类的方法
public class InnerTest {
@Test
public void outer04() {
new Outer04().innerRun();
}
}
调取输出
奔跑吧兄弟
静态方法调用及局部内部类静态方法
静态方法中的局部内部类
public class Outer05 {
public static void innerRun() {
class Inner {
public static void run() {
System.out.println("奔跑吧兄弟");
}
}
Inner.run();
}
}
使用局部内部类的方法
public class InnerTest {
@Test
public void outer05() {
Outer05.innerRun();
}
}
调取输出
奔跑吧兄弟
静态方法调用及局部内部类非静态方法
实例化局部内部类点方法名
public class Outer06 {
public static void innerRun() {
class Inner {
public void run() {
System.out.println("奔跑吧兄弟");
}
}
new Inner().run();
}
}
public class InnerTest {
@Test
public void outer06() {
Outer06.innerRun();
}
}
输出
奔跑吧兄弟
非静态方法调用及局部内部类非静态方法
public class Outer07 {
public void innerRun() {
class Inner {
public void run() {
System.out.println("奔跑吧兄弟");
}
}
new Inner().run();
}
}
使用实例化外部类调用非静态方法
public class InnerTest {
@Test
public void outer07() {
new Outer07().innerRun();
}
}
输出
奔跑吧兄弟
匿名内部类
直接实例化对象 ,不拿变量接收的对象为匿名对象
public class Outer08 {
public void innerRun() {
class Inner {
}
new Inner() {
public void run() {
System.out.println("奔跑吧兄弟");
}
}.run();
}
}
使用匿名对象调用run方法的方法调取
public class InnerTest {
@Test
public void outer08() {
new Outer08().innerRun();
}
}
输出
奔跑吧兄弟
Object是所有类的父类,使用所有类的超类Object类调用局部内部类非静态方法称之为匿名内部类
public class Outer09 {
public void innerRun() {
new Object() {
public void run() {
System.out.println("奔跑吧兄弟");
}
}.run();
}
}
public class InnerTest {
@Test
public void outer09() {
new Outer08().innerRun();
}
}
输出
奔跑吧兄弟