学习面向对象内容的三条主线
- Java类及类的成员:(重点)属性、方法、构造器;(熟悉)代码块、内部类
- 面向对象的特征:封装、继承、多态、(抽象)
- 其他关键字的使用:this、super、package、import、static、final、interface、abstract等
1、面向对象特征一--封装
1.1 封装的原则与使用
封装的原则:将属性隐藏起来,若要访问某个属性,提供公共方法对其访问。
如何封装:
使用private关键字来修饰成员变量。
对需要访问的成员变量,提供公共对应的一对setter、getter方法
1.2 private关键字
1. private是一个权限修饰符,代表最小权限。
2. 可以修饰成员变量和成员方法。
3. 被private修饰后的成员变量和成员方法,只在本类中才能访问
public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public void StudentInfo(String name, int age) {System.out.println(name + " " + age);}public String getName() {System.out.println(name);return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
public class StudentTest {public static void main(String[] args) {Student student = new Student();student.setName("三石");student.setAge(18);System.out.println(student);}
}
2、面向对象特征二--继承
2.1 继承概述
2.1.1 继承概念
继承:就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类的非私有的属性和行为。
2.1.2 继承特点
- 子类自动拥有父类非私有的成员
- 子类也可以拥有自己的成员
2.1.3 继承好处
- 提高代码复用性
- 有利于功能的拓展。
- 类与类之间产生了关系,继承是多态的前提
2.1.4 继承格式
通过extends关键字,可以声明一个子类继承另外一个父类,定义格式如下:
格式:
class 父类 { ... }
class 子类 extends 父类 { ... }
代码演示:
package com.suyv;
/**
*@Author: 憨憨浩浩
*@CreateTime: 2023-12-05 10:56
*@Description: 创建Animal父类
*/
public class Animal {public String name;public int age;public String color;public void say(){System.out.println("动物会叫!!!");}public void eat() {System.out.println("动物会吃!!!");}
}package com.suyv;
/**
*@Author: 憨憨浩浩
*@CreateTime: 2023-12-05 10:58
*@Description: 创建Animal子类Cat类
*/
public class Cat extends Animal{}package com.suyv;
/**
*@Author: 憨憨浩浩
*@CreateTime: 2023-12-05 10:58
*@Description: 创建Animal子类Dog类
*/
public class Dog extends Animal{}package com.suyv;
/**
*@Author: 憨憨浩浩
*@CreateTime: 2023-12-05 10:59
*@Description: 测试类
*/
public class AnimalTest {public static void main(String[] args) {Cat cat = new Cat();cat.say();cat.eat();Dog dog = new Dog();dog.say();dog.eat();}
}
2.2 继承中成员访问特点
2.2.1 子类访问父类非私有成员
public class Father {// 私有的成员变量private int num = 10;// 非私有的成员变量public int num2 = 20;// 私有的成员方法private void mothod(){System.out.println(num);System.out.println(num2);}// 非私有的成员方法public void show(){System.out.println(num);System.out.println(num2);}
}public class Son extends Father {//子类也可以有自己的东西public void function(){//子类不能访问父类中私有的成员变量// System.out.println(num);System.out.println(num2);}
}public class SonTest {public static void main(String[] args) {Son s = new Son();// s.num =200; //子类不能访问父类中的私有的成员变量s.num2 = 100;// s.mothod(); //子类不能访问父类中的私有的成员方法s.function(); //也可以访问自己的方法s.show();}
}
2.2.2 成员变量
2.2.2.1 成员变量不重名
如果子类父类中出现不重名的成员变量,这时的访问是没有影响的。代码如下:
//父类
public class Father {int num = 10;
}//子类
public class Son extends Father {//子类成员变量int num2 = 20;//子类成员方法public void function(){// 访问父类中的num,System.out.println("Fu num="+num); //10 // 访问子类中的num2System.out.println("Zi num2="+num2); // 20}
}//测试类
public class SonTest {public static void main(String[] args) {Son s = new Son();s.function();}
}
2.2.2.2 成员变量重名
如果子类父类中出现重名的成员变量,这时的访问是没有影响的。代码如下:
//父类
public class Father {int num = 10;
}//子类
public class Son extends Father {int num = 20;//子类成员方法public void function(){//如果子类成员变量的名与父类成中变量名一样,就近原则System.out.println("num="+num); //20 }
}//测试
public class SonTest {public static void main(String[] args) {Son s = new Son();s.function();}
}
子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用super关键字,修饰父类成员变量,类似于之前学过的this
2.2.3 成员方法
2.2.3.1 成员方法不重名
如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类不存在就会执行父类中相应的方法。代码如下:
//父类
public class Father {public void show(){System.out.println("我是父类Father");}
}//子类
public class Son extends Father {public void show2(){System.out.println("我是子类Son");}
}//测试
public class SonTest {public static void main(String[] args) {Son s = new Son();s.show();//调用父类方法s.show2();//调用子类方法}
}
2.3.3.2 成员方法重名
参考方法重写
2.2.4 构造器执行特点
1.构造方法的名字是与类名一致的。所有子类是无法继承父类构造方法的。
2.构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() , 表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。
//父类
public class Father {private int num;//父类的构造方法public Father(){System.out.println("父类的构造方法");}public Father(int num) {this.num = num;}public void show1(){System.out.println(num);}
}//子类
public class Son extends Father {//子类无参构造方法public Son(){// 子类构造方法中的第一行默认有 super() ,给父类进行初始化的// 作用:因为继承必须先调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。super();System.out.println("子类的构造方法");}//子类有参构造方法public Son(int num2) {super(34);this.num2 = num2;}public void show2(){System.out.println(num2);}}//测试
public class Test {public static void main(String[] args) {//在每次创建子类对象时,都会先初始化父类构造方法,再创建其子类对象本身。Son s = new Son();Son s = new Son();//每一次实例子类对象,都会先访问父类的无参构造 (这里两次)//访问有参构造Son s = new Son(2000);s.show1();s.show2();}
}
注意事项:
在子类构造方法中的第一行默认有 super() ,给父类进行初始化的
在子类构造方法中可以手动调用父类其他重载的构造方法
格式: super(参数列表);
super 是写在子类的构造方法的第一行。
2.3 继承的特点
1.java只支持单继承,不支持多继承
2.Java支持多层继承(继承体系)
3.子类和父类是一种相对的概念,一个父类可以有很多个子类
3、方法重写(Override)
如果子类父类中出现重名的成员方法,这时访问是一种特殊情况,叫做方法重写(Override)
3.1 什么是方法重写
方法重写:子类中出现与父类一模一样的方法时(返回值类型、方法名和参数列表都相同),会出现覆盖效果,也称为复写或者重写。声明不变,重新实现。
package com.suyv;
/**
*@Author: 三石
*@CreateTime: 2023-12-05 10:56
*@Description: 创建Animal父类
*/
public class Animal {public String name;public int age;public String color;public void say(){System.out.println("动物会叫!!!");}public void eat() {System.out.println("动物会吃!!!");}
}package com.suyv;
/**
*@Author: 三石
*@CreateTime: 2023-12-05 10:58
*@Description: 创建Animal子类Cat类
*/
public class Cat extends Animal{@Overridepublic void say() {System.out.println("小猫会喵喵叫");}@Overridepublic void eat() {System.out.println("小猫爱吃鱼");}
}package com.suyv;
/**
*@Author: 三石
*@CreateTime: 2023-12-05 10:58
*@Description: 创建Animal子类Dog类
*/
public class Dog extends Animal{@Overridepublic void say() {System.out.println("小狗会汪汪叫");}@Overridepublic void eat() {System.out.println("小狗爱啃骨头");}
}package com.suyv;
/**
*@Author: 三石
*@CreateTime: 2023-12-05 10:59
*@Description: 测试类
*/
public class AnimalTest {public static void main(String[] args) {Cat cat = new Cat();cat.say();cat.eat();Dog dog = new Dog();dog.say();dog.eat();}
}
3.2 方法重写的注意事项
1. 子类方法重写父类方法,必须要保证权限大于等于父类权限,最好修饰权限一样。
2. 子类方法重写父类方法,返回值类型、方法名和参数列表都要一模一样。
4、关键字:super
4.1 super的理解
在Java类中使用super来调用父类中的指定操作:
- super可用于访问父类中定义的属性
- super可用于调用父类中定义的成员方法
- super可用于在子类构造器中调用父类的构造器
注意:
- 尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员
- super的追溯不仅限于直接父类
- super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识
4.2 super的使用场景
- 子类中调用父类被重写的方法
- 子类中调用父类中同名的成员变量
- 子类构造器中调用父类的构造器
4.2 this和super
4.3.1 this和super的含义
this:代表当前对象的引用(谁调用就代表谁)。
super:前提:继承关系 。 代表父类的存储空间标识(可以理解为父亲的引用)。
4.3.2 super和this的用法
访问成员:
this.成员变量 ‐‐ 本类的
this.成员方法名() ‐‐ 本类的
super.成员变量 ‐‐ 父类的
super.成员方法名() ‐‐ 父类的
代码演示:
class Animal {public void eat() {System.out.println("animal : eat"); }
}class Cat extends Animal {public void eat() {System.out.println("cat : eat");}public void eatTest() {this.eat(); // this 调用本类的方法 super.eat(); // super 调用父类的方法 }
}public class ExtendsDemo08 {public static void main(String[] args) { Animal a = new Animal();a.eat();Cat c = new Cat();c.eatTest();}
}
访问构造
this(...) ‐‐ 本类的构造方法
super(...) ‐‐ 父类的构造方法
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
super()和this()都必须是在构造方法的第一行,所以不能同时出现。
super和this的区别?
super的用法,前提:一定要有继承关系,子类无法访问父类的成员,通过super关键字来找父类引用
super.成员变量 子类访问的父类中的成员变量
super.成员方法 子类访问的父类中的成员方法
super() 子类访问父类的无参构造方法
super("xx") 子类访问父类中有参构造方法
this的用法 代表当前对象的引用(谁调用this就代表谁)
this.成员变量 本类的成员变量
this.成员方法 本类的成员方法
3、抽象类与抽象方法
3.1 语法格式
抽象方法:只有方法的声明,没有方法体的方法,就是抽象方法。
抽象类:抽象方法所在的类必定是一个抽象类。
抽象类的语法格式
[权限修饰符] abstract class 类名{}
[权限修饰符] abstract class 类名 extends 父类{}
抽象方法的语法格式
[其他修饰符] abstract 返回值类型 方法名([形参列表]);
注意:抽象方法没有方法体
3.2 定义方法
3.2.1 抽象方法
使用abstract关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
定义格式:
修饰符 abstract 返回值类型 方法名 (参数列表);
演示:
public abstract void run();
3.2.2 抽象类
如果一个类包含抽象方法,那么该类必须是抽象类。
定义格式:
public abstract class 类名字 {
}
演示:
public abstract class Animal {public abstract void run();
}
3.3 抽象的使用
具体的子类继承抽象的父类必须重写父类所有的抽象方法
抽象的子类继承抽象的父类,不用再去重写父类的所有抽象方法,这种是没有意义。
public class AbstractTest {public static void main(String[] args) {B b = new B();b.say();b.sleep();}
}
abstract class A{public abstract void say();public void sleep(){System.out.println("sleep");}
}class B extends A{@Overridepublic void say() {System.out.println("我是B");}}
3.4 抽象的注意事项
有抽象方法的类,这个类一定是抽象类
抽象类中可以有抽象方法,也可以有普通方法
抽象类有构造方法
抽象类不能实例化
抽象类中的普通方法如何调用,能过子类继承过来即可调用
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
3.5 抽象类关键字的使用
abstract不能和以下关键字一块使用
private 冲突
final 冲突
static 冲突
public abstract class Fu {//非法的修饰符组合// private abstract void show();//非法的修饰符组合// final abstract void method();//非法的修饰符组合// static abstract void method();//可以有静态方法public static void method1(){System.out.println("method1");}}
补充:标准JavaBean编写
JavaBean是Java语言编写类的一种标准规范。
符合JavaBean的类,有构造方法,提供操作属性的set、get方法
public class ClassName{ //成员变量//构造方法//无参构造方法【必须】 //有参构造方法【建议】 //成员方法 //getXxx()//setXxx()
}
编写标准JavaBean类
public class Student {// 成员变量private String name;private int age;// 构造器public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}// setter和getter方法public String getName() {System.out.println(name);return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}// 重写toString方法@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}