JAVA 知识 回顾 2
面向对象
继承
关键字: extends
特点:
- 提高代码的复用性
- 让类与类之间产生关系,才有了多态的特性
注意:
- 不能为了获取其他类的功能,简化代码而继承
- 必须类与类有所属关系才可以继承。所属关系
Java语言中只支持单继承,不支持多继承
多继承存在安全隐患,当多个父类中定义了相同的功能,但功能内容不同是,子类对象不确定运行哪一个
Java保留了多继承机制,并用另一种形式体现,接口(多实现,implements)
public class Main {
public static void main(String[] args)
{
Student s1 = new Student();
s1.setName("Yz");
s1.setAge(25);
s1.study();
}
}
/**
设置父类,保存通用的一些属性,
不要设置私有,否则继承无法获取
*/
class People{
protected String name;
protected int age;
}
/**
子类继承People父类
*/
class Student extends People
{
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public void study()
{
System.out.println("My name is"+this.name);
System.out.println(this.age+" years old");
}
}
多层继承
Java支持多层继承,也就是有一个继承体系
想要使用体系,先要查阅父类的藐视,因为弗雷中定义的是该类中共性功能
通过了解共性功能,就可以知道该体系的基本功能
查阅父类功能,创建子类对象使用功能
class People
{
·····
}
class Student extends People
{
·····
}
class Children extends Student
{
·····
}
聚集关系
按照事物联系的紧密程度划分为
聚合:例如球队与球员关系,缺少队员是可行的
组合:例如人与人体器官的关系,缺少器官是万万不行的
子父类关系
类中成员:
- 变量
- 函数
- 构造函数
super —— 父类对象引用
子类要访问本类变量用 this
子类访问父类中的同名变量用 super
public class Main {
public static void main(String[] args)
{
Student s = new Student();
s.showAge();
}
}
class People{
protected int age = 25;
}
/**
类中的变量,引用默认为this
*/
class Student extends People
{
int age = 2;
public void showAge(){
System.out.println(age);//2
System.out.println(this.age);//2
System.out.println(super.age);//25
}
}
重写(覆盖)
子父类的方法名相同
当子类继承父类,会沿袭父类的功能,到子类中,但子类中虽具备该功能,但功能内容不一样
这时,没必要定义新功能,而是使用覆盖,保留父类的功能定义,并重写内容功能
注意:
- 子类覆盖父类,必须保证子类权限大于父类权限,才可以覆盖,否则编译失败
- 静态只能覆盖静态
权限问题:
public > 没有修饰 > private
/**
子类speak() 会覆盖 父类 的 speak()
*/
public class Main {
public static void main(String[] args)
{
Student s = new Student();
s.speak();//你好 , 世界!!
}
}
//父类
class People{
public void speak(){
System.out.println("Hello WOrld!!!");
}
}
//子类
class Student extends People
{
public void speak(){
System.out.println("你好 , 世界!!");
}
}
当子类继承父类的功能,并添加一些新的内容
/**
通过super在子类功能
*/
//子类
class Student extends People
{
public void speak(){
super.speak();
System.out.println("你好 , 世界!!");
}
}
重载:值看同名函数的参数列表
重写(覆盖):字符类方法要一模一样
子父类构造函数
super(); —— 引用父类空参数的构造函数
this(); —— 引用本类的构造函数
在子类对象进行初始化时,父类构造函数也会运行,因为子类构造函数默认第一行有一条隐式的 super();
super();语句必须放在第一行
子类中 所有的构造函数第一行默认都 是 super();
public class Main {
public static void main(String[] args)
{
Student s = new Student();
Student s1 = new Student(25);
// This is People
// This is Student
// This is People
// age:25
}
}
class People{
People(){
System.out.println("This is People");
}
}
class Student extends People
{
Student(){
System.out.println("This is Student");
}
Student(int age){
System.out.println("age:"+age);
}
}
子类一定要访问父类中的构造函数
因为子类对象在建立时,需要先查看父类是如何对这些数据进行初始化,所以子类在对象初始化时,要先访问一下父类中的构造函数
要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定
public class Main {
public static void main(String[] args)
{
Student s = new Student();
// num:58
// This is Student
}
}
class People{
People(){
System.out.println("This is People");
}
People(int num){
System.out.println("num:"+num);
}
}
class Student extends People
{
Student(){
super(58);
System.out.println("This is Student");
}
}
子类的所有构造函数,默认都会访问父类中的空参数构造函数
当父类中没有空参数构造函数时,子类必须手动通过super或者this语句形式来指定要访问的构造函数
子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数
子类中至少会有一个构造函数会访问父类的构造函数
所有类继承自 object类
final关键字
final:最终
修饰符:
- 可以修饰类,函数,变量
- 被final修饰的 类不可以被继承
- 被final修饰的 方法不能被复写
- 被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,也可以修饰局部变量
- 内部类定义在类中的局部位置上,只能访问该局部被final修饰的局部变量
final修饰的变量,称为常量,所有的的字母都是大写,若由多个单词组成,使用连接符( _ )连接
抽象类()
当多个类中出现相同功能,但功能主体不同,这时可以进行抽取,抽取功能定义,而不抽取功能主体
class All{
void show(){};
}
class A extends All{
void show(){
System.out.println("A");
}
}
class B extends All{
void show(){
System.out.println("B");
}
}
抽象类:abstract,不必在意内容
特点:
- 抽象方法一定在抽象类中
- 抽象方法和抽象类必须被abstract关键字修饰
- 抽象类不可以用 new 创建对象,因为调用抽象方法没意义
- 抽象类中的抽象方法要被使用,必须有子列复写所有的抽象方法后,建立子类对象调用
若子类支付该部分抽象方法,则该子类还是一个抽象类
abstract class All{
abstract void show();
abstract void set();
}
class A extends All{
void show(){
System.out.println("A");
};
void set(){};
}
class B extends All{
void show(){
System.out.println("B");
}
void set(){};
}
继承抽象类,会强制子类进行一些方法
抽象类和一般类没有太大的不同
抽象类不可以实例化
抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法
抽象类中可以不定义抽象方法,目的 : 不让该类建立对象
模板方法模式
在定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部,
那么就将不确定的部分暴露,公外部程序继承使用
获取当前的时间戳
System.currentTimeMillis()
public class Main {
public static void main(String[] args)
{
SetTime s1 = new SetTime();
System.out.println(s1.getTime());
}
}
abstract class GetTime
{
/*
* System.currentTimeMillis(); 获取当前时间的时间戳
* runRode(); 一个接口,从而运行外部程序
*/
public final long getTime(){
Long start = System.currentTimeMillis();
runRode();
Long end = System.currentTimeMillis();
return end-start;
}
/*
* 一个接口,可以被继承,然后重载,通过抽象
*/
public abstract void runRode();
}
/*
* 自类继承父类的内容,同时通过重载runRode,来获取runRode中程序的执行时间
*/
class SetTime extends GetTime{
public void runRode(){
for (int i = 0; i < 2000; i++) {
System.out.print(2);
}
System.out.println();
}
}
接口
初期理解:特殊的抽象类(抽象类中的全部方法都是抽象的)
interface —— 用于定义接口
class —— 用于定义类
格式特点:
- 接口中常见的定义:常量,抽象方法
- 接口中的成员都有固定修饰符
- 常量 —— public static final
- 方法 —— public abstract
接口中的成员都是public
默认情况下,只要定义 interface ,接口成员的修饰符会默认,可以不写或者少写
通常情况下,要写全,方便阅读
interface Circle{
public static final double PI = 3.14;
public abstract double show();
}
接口是不可以创建方法的,因为有抽象方法,需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实现实例化,否则子类是一个抽象类
s使用子类引用接口时,不能使用继承 extends ,而应该用 实现 implements
public class Main {
public static void main(String[] args)
{
Area s = new Area(8);
System.out.println(s.show());
}
}
//定义一个接口
interface Circle{
public static final double PI = 3.14;
public abstract double show(int r);
}
//计算圆的面积,接口定义的内容,不能使用继承 extends,应该使用实现 implements
class Area implements Circle,Rect{
private double r;
Area(double r)
{
this.r = r;
}
public double show(){
double R = this.r;
return PI*R*R;
}
}
类与类之间是继承 extends
类与接口之间 是 实现 Implements
接口可以被类多实现(implements),Java支持多实现(implements)
interface Circle{
public static final double PI = 3.14;
public abstract double show();
}
interface Rect{
public abstract double show();
}
class Area implements Circle,Rect{
public double show(){
return PI;
};
}
接口与接口之间,是继承 , 允许存在多继承
interface Circle{
public abstract void circle();
}
interface Rect{
public abstract void rect();
}
interface All extends Circle,Rect{
public abstract void all();
}
class Show implements All{
public void circle(){};
public void rect(){};
public void all(){};
}
接口特点
- 接口对外暴露规则
- 接口时程序的功能扩展,降低耦合性
- 接口可以用来多实现
- 类域接口之间是实现关系,类可以继承一个类的同事实现多个接口
- 接口与接口之间可以有继承关系
接口实例
基本内容定义在类中
扩展功能定义在接口中
public class Main {
public static void main(String[] args)
{
Worker w = new Worker();
w.sleep();//睡觉了!
w.speak();//我是工人,我需要工作!
w.work();//搬砖
Student s = new Student();
s.sleep();//睡觉了!
s.speak();//我是学生,不需要工作!
}
}
//抽象类,抽象方法speak , 一般方法 sleep
abstract class People{
abstract void speak();
void sleep(){
System.out.println("睡觉了!");
}
}
//接口,扩展一个工作
interface Working{
public abstract void work();
}
/*
* 这是一个工人类
* 继承 sleep
* 抽象 speak
* 实现 work
*/
class Worker extends People implements Working{
void speak() {
System.out.println("我是工人,我需要工作!");
}
void sleep() {
super.sleep();
}
public void work() {
System.out.println("搬砖");
}
}
/*
* 这是一个学生类
* 继承sleep
* 抽象speak
*/
class Student extends People{
void speak() {
System.out.println("我是学生,不需要工作!");
}
void sleep() {
super.sleep();
}
}
多态
可以理解为 事物存在的多种体现形态
多态的体现:
父类的引用指向了自己的子类对象
父类的引用可以接受自己的子类对象
但是产生的对象不能调用子类的方法
多态的前提
必须是类与类之间的关系,继承或实现
通常子类覆盖父类
多态的前提
提高了扩展性,但是只能使用父类的引用访问父类的成员
多态的好处
多态的出现大大提高了程序的扩展性
public class Main {
public static void main(String[] args)
{
// 原本的方式
People s = new Student();
s.speak();
// 封装的方法
function(new Worker());
}
public static void function(People p)
{
p.speak();
}
}
abstract class People{
abstract void speak();
// 可以每添加一个子类,就可以添加一些子类的方法,用于被覆盖
}
class Worker extends People {
void speak() {
System.out.println("我是工人,我需要工作!");
}
}
class Student extends People {
void speak() {
System.out.println("我是学生,我需要学习!");
}
public void work() {
System.out.println("学习");
}
}
转型
类型提升,向上转型
People s = new Student();
若要调用子类的特有的方法时,强制将父类引用转成子类类型,向下转型
Student c = (Student)s;
不能将父类对象转化成子类类型
应用
子类覆盖父类的方法
当通过父类 去引用子类方法,会执行覆盖之后的方法
public class Main {
public static void main(String[] args) {
// 封装的方法
function(new Student());
}
public static void function(People p)
{
p.speak();
p.sleep();
}
}
abstract class People{
abstract void speak();
// 可以每添加一个子类,就可以添加一些子类的方法,用于被覆盖
public void sleep() {
System.out.println("睡觉");
}
} class Worker extends People {
void speak() {
System.out.println("我是工人,我需要工作!");
}
}
class Student extends People {
void speak() {
System.out.println("我是学生,我需要学习!");
}
public void sleep() {
System.out.println("熬夜啊,不能睡");
}
}
结果:
我是学生,我需要学习!
熬夜啊,不能睡
多态的特点
编译看左边,运行看右边
People p = new Student();
在多态中,成员变量的特点 :
- 无论是在编译还是运行,都参考左边(引用性变量所属的类)
在多态中,静态成员函数的特点:
- 当方法为静态,子类覆盖之后,结果为 父类方法内容
- 当方法为非静态,子类覆盖之后,结果为 覆盖后的方法内容
public class Main {
public static void main(String[] args) {
People p = new Student();
p.sleep();//睡觉
Student s = new Student();
s.sleep();//熬夜啊,不能睡
}
}
abstract class People{
public static void sleep() {
System.out.println("睡觉");
}
}
class Student extends People {
public static void sleep() {
System.out.println("熬夜啊,不能睡");
}
}