1、初识面向对象
面向过程&面向对象
🔷面向过程思想
🔷步骤清晰简单,第一步做什么,第二步做什么.....
🔷面对过程适合处理一些较为简单的问题
🔷面向对象思想
🔷物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。
最后,才对某个分类下的细节进行面向过程的思索。
🔷面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
🔷对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系 统。但是,具体到微观操作,仍然需要面向过程的思路去处处理。
什么是面向对象
🔷面向对象编程(Object-Oriented Programming, OOP)
🔷面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
🔷抽象
🔷三大特性:
🍉封装
🍉继承
🍉多态
🔷从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
🔷从代码运行角度考虑是先有类后有对象。类是对象的模板。
2、方法回顾和加深
🔷方法的定义
🍉修饰符
🍉返回类型
🍉break:跳出switch,结束循环 和return的区别
🍉方法名:注意规范就OK 见名知意
🍉参数列表:(参数类型,参数名)......
🍉异常抛出:疑问,后面讲解
代码实例
public class Demo1 {
// main 方法
public static void main(String[] args) {
}
/*
修饰符 返回值类型 方法名(){
//方法体
return 返回值;
}
*/
// return 结束方法,返回一个结果!
public String sayHello(){
return "Hello,World";
}
public void hello(){
return ;
}
public int max(int a,int b){
return a>b?a:b; //三元运算符
}
public void readFile(String file)throws IOException{}
}
🔷方法的调用
🍉静态方法
🍉非静态方法
🍉形参和实参
🍉值传递和引用传递
🍉this关键字
public class Demo7 {
public static void main(String[] args) {
// 实际参数和形式参数的类型要对应
int add = Demo7.add(1, 2);
System.out.println(add);
}
public static int add(int a,int b){
return a+b;
}
}
🔷值传递和引用传递
//值传递 java是值传递
public class Demo8 {
public static void main(String[] args) {
int a = 1;
System.out.println(a); //1
Demo8.change(a);
System.out.println(a); //1
}
//返回值为空
public static void change(int a){
a = 10;
}
}
//引用传递:一般传递对象,本质还是值传递
//听起来有点晕!没有了解对象!内存!
public class Demo9 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name); //null
Demo9.change(person);
System.out.println(person.name); //冯宝宝
}
public static void change(Person person){
//person是一个对象:指向的----> Person person = new Person();这是一个人,可以改变属性!
person.name = "冯宝宝";
}
}
//一个类里面只能有一个public class 但是可以有多个class
//定义了一个Person类,有一个属性name
class Person{
String name; //默认值null
}
3、对象的创建分析
💥万物皆对象
世界是由什么组成的?
分类是人们认识世界的一个很自然的过程,在日常生活中会不自觉地进行分类
💥身边的对象
💥对象的特征—属性
🔷属性:对象具有的各种特征
🔷每个对象的每个属性都拥有特定值
🍉例如:张浩和李明的年龄、姓名不一样
💥对象的特征—方法
🔷方法:对象执行的操作
💥对象的属性和方法
🔷列出尼古拉斯·凯奇驾驶的这辆法拉利F360 Spider的属性和方法
🔷列出小狗对象的属性和方法
💥封装
🔷对象同时具有属性和方法两项特性
🔷对象的属性和方法通常被封装在一起,共同体现事物的特性, 二者相辅相承,不能分割
💥小结
🔷说一说教室里的对象
🔷描述他们的属性和方法
💥从对象抽象出“类”
🔷抽取出下列对象的共同特征(属性和方法)
💥类
💥类和对象的关系
🔷类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物.
🍉动物、植物、手机、电脑......
🍉Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
🔷对象是抽象概念的具体实例
🍉张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
🍉能够体现出特点,展现出功能的是具体 的实例,而不是一个抽象的概念.
🔷类是抽象的概念,仅仅是模板
比如说:“人”
🔷对象是一个你能够看得到、摸得着的具体实体
💥创建于初始化对象
🔷使用new关键字创建对象
🔷使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构 造器的调用。
💥Java类模板
🔷类将现实世界中的概念模拟到计算机程序中
💥定义类2-1
🔷定义一个类的步骤
💥类示例
🔷在不同学校,会感受到相同的环境和教学氛围,用类的思想输出中心信息
💥类示例2-2
💥如何创建和使用对象
💥面向对象(OO)的优点
代码实例
//学生类
public class Student {
//属性:字段
String name; //null
int age; //0
//方法 this:代表当前这个类
public void study(){
System.out.println(this.name+"在学习");
}
}
// 一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//类:抽象的,实例化 new 快捷键 :alt+enter回车
//类实例化后悔返回一个自己的对象!
//fbb对象就是一个Student类的具体实例!
Student fbb = new Student();
//赋值
fbb.name="冯宝宝";
fbb.age =18;
//打印
System.out.println(fbb.name);
System.out.println(fbb.age);
Student fjq = new Student();
//赋值
fjq.name="冯加奇";
fjq.age =18;
//打印
System.out.println(fjq.name);
System.out.println(fjq.age);
}
}
💥构造器详解
🔷类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩个特点:
1.必须和类的名字相同
⒉必须没有返回类型,也不能写void
🔷构造器必须要掌握
一个类即使什么都不写,它也会存在一个方法,这就是构造器
代码实例
public class Person {
//一个类即使什么都不写,它也会存在一个方法
//显示的定义构造器
String name;
//无参构造的作用
//实例化初始值
//1,使用new关键字,本质还是调用构造器,断点调试
//2,用来初始化值
public Person(){
// this.name = "冯宝宝";
}
//有参构造:一旦定义了有参构造,无参就必须显示定义,断点调试
public Person(String name){
this.name = name;
}
//alt+insert:快捷键,快速生成有参构造和无参构造
}
public class Application2 {
public static void main(String[] args) {
// new 实例化了一个对象
Person person = new Person("冯宝宝");
System.out.println(person.name); //冯宝宝
}
}
💥构造器总结:
1.和类名相同
2.没有返回值
作用:
1. new本质在调用构造方法
2.初始化对象的值
注意点:
1. 定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
alt+insert:快捷键,快速生成有参构造和无参构造
this:代表当前这个类
💥创建对象内存分析
代码实例
public class Pet {
public String name;
public int age;
//无参构造
public void shout(){
System.out.println("叫了一声");
}
}
public class Application {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "旺财";
dog.age = 3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
}
}
总结
1.类与对象
类是一个模板:抽象,对象是一个具体的实例
2.方法
定义、调用!
3.对应的引用
引用类型:基本类型(8)
对象是通过引用来操作的:栈——>堆(地址)
4.属性:字段Field 成员变量
默认初始化:
数字:0 0.0
char:u0000
boolean:false
引用:null
修饰符 属性类型 属性名 = 属性值
5.对象的创建和使用
必须使用 new 关键字创建对象,构造器 Person fbb = new Person();
对象的属性:fbb.name
对象的方法:fbb.sleep();
6.类:
静态的属性:属性
动态的行为:方法
4、面向对象三大特性
❤️封装
🔷该露的露,该藏的藏
🍉我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,
🍉不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
🔷封装(数据的隐藏)
🍉通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
🔷记住这句话就够了:属性私有,get/set
💥什么是封装(🌟🌟🌟🌟重点)
🔷面向对象三大特征之一 ——封装
🍉封装的概念
封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
💥封装的好处
💥如何使用封装
🔷封装的步骤
代码实例
/*
* 1.提高程序的安全性,保护数据
* 2.隐藏代码的实习细节
* 3.统一接口 get set
* 4.系统可维护性增加了
*/
//学生类 // private:私有
public class Student {
//属性私有化
private String className; //名字
private int id; //学号
private char sex; //性别
private int age; //年龄
//提供一些可以操作这个属性的方法!
//提供一些public 的 get set方法
//get 获得这个数据
public String getClassName(){
return this.className;
}
//set 给这个数据设置值
public void setClassName(String className){
this.className = className;
}
// 快速生成get、set方法 快捷键 alt+insert
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 120 || age < 0) { //不合法
this.age = 3;
}else{
this.age = age;
}
}
//学习()
//睡觉()
}
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.setClassName("冯宝宝");
System.out.println(student.getClassName());
student.setAge(999); //不合法
System.out.println(student.getAge());
}
}
💥封装的好处
💥this的用法(🌟🌟🌟🌟重点)
🔷this关键字的用法
💫调用属性
💫调用方法
💫调用构造方法
💫如果使用,必须是构造方法中的第一条语句
public class Student {
//属性私有化
private String className; //名字
private int id; //学号
private char sex; //性别
private int age; //年龄
public Student() {
//this("冯宝宝",8,'男',18);
System.out.println(this);
}
public Student(String className, int id, char sex, int age) {
//this();
this.className = className;
this.id = id;
this.sex = sex;
this.age = age;
}
}
💥总结
❤️继承
🔷继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
🔷extends的意思是“扩展”。子类是父类的扩展。
🔷JAVA中类只有单继承,没有多继承!
一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子
🔷继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
🔷继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。
子类继承父类,使用关键字extends来表示。
🔷子类和父类之间,从意义上讲应该具有"is a"的关系.
🔷object类
🔷super :重点
🔷方法重写:重点
💥为什么使用继承
🔷生活中的基础
💥如何使用继承
🔷使用继承
💠编写父类
💠编写子类,继承父类
代码实例
//在java中,所有的类,都默认直接或者间接继承object类
//人类: 父类
public class Person {
//public : 公开的
//protected: 受保护的(比默认的优先级高)
//private: 私有的
//default: 默认的
private int money = 10_000_000;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public void say(){
System.out.println("说了一句话......");
}
}
// 学生类 is 人:派生类,子类
// 子类继承了父类,就会拥有父类的全部方法!
public class Student extends Person{
//Ctrl+H
}
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
System.out.println(student.getMoney());
}
}
💥理解继承
🔷继承类型
需要注意的是 Java 不支持多继承,但支持多重继承。
代码实例
//在java中,所有的类,都默认直接或者间接继承object类
//人类: 父类
public class Person {
public Person() {
System.out.println("Person无参执行了");
}
protected String name = "冯宝宝";
//私有的东西无法被继承
public void print(){
System.out.println("Person");
}
}
// 学生类 is 人:派生类,子类
// 子类继承了父类,就会拥有父类的全部方法!
public class Student extends Person{
//Ctrl+H
public Student() {
//隐藏代码:调用了父类的无参构造
super();//调用父类的构造器,必须要在子类构造器的第一行
System.out.println("Student无参执行了");
}
private String name="马云";
public void print(){
System.out.println("Student");
}
public void test1(){
print(); //Student
this.print(); //Student
super.print(); //Person
}
public void test2(String name){
System.out.println(name);//乐学优课
System.out.println(this.name);//马云
System.out.println(super.name);//冯宝宝
}
}
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test2("乐学优课");
System.out.println("----------");
student.test1();
}
}
💥方法的重写(override)
🔷方法重写只存在于子类和父类(包括直接父类和间接父类)之间。
在同一个类中方法只能被重载,不能被重写
🔷 静态方法不能重写
💠父类的静态方法不能被子类重写为非静态方法 //编译出错
💠父类的非静态方法不能被子类重写为静态方法;//编译出错
💠子类可以定义与父类的静态方法同名的静态方法(但是这个不是覆盖)
代码实例
public class Application {
//静态的方法和非静态的方法区别很大!
//静态方法:方法的调用只和左边(定义的数据类型)有关
//非静态:重写
public static void main(String[] args) {
//方法的调用只和左边(定义的数据类型)有关
A a = new A();
a.test();
//父类的引用指向了子类
B b = new A();//子类重写了父类的方法
b.test();
}
}
//继承
public class A extends B{
// public static void test(){
// System.out.println("A-->text()");
// }
//Override 重写
@Override//注解:有功能的注释!
public void test() {
//super.test();//默认调用父类的test()
System.out.println("A-->test()");
}
}
//重写是方法的重写,与属性无关
public class B {
// public static void test(){
// System.out.println("B-->text()");
// }
public void test(){
System.out.println("B-->text()");
}
}
💥抽象类
🔷abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,
那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
🔷抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
🔷抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
🔷抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
🔷子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
代码实例
//abstract 抽象类 类:extends :单继承 ~ (接口可以多继承)插座~
public abstract class Action {
// 约束~有人帮我们实现~
// abstract,抽象方法,只有方法名字,没有方法的实现!
public abstract void doSomething();
//1.不能new 这个抽象类,只能靠子类去实现它;约束!
//2.抽象类中可以写普通方法~
//3.抽象方法必须在抽象类中~
// 抽象的抽象:约束!
public void show(){
}
//抽象类的意义: 把公共的抽象出来~ 提高开发效率
}
public class A extends Action{
@Override
public void doSomething() {
}
}
public class Application {
public static void main(String[] args) {
new Action(); //报错 不能实例化
}
}
💥static
💦概述
🍭static 关键字是静态的意思,是Java中的一个修饰符,可以修饰成员方法,成员变量
💦static修饰的特点
🍭被类的所有对象共享是我们判断是否使用静态关键字的条件
🍭随着类的加载而加载,优先于对象存在对象需要类被加载后,才能创建
🍭可以通过类名调用也可以通过对象名调用
💦注意事项(理解)
🍭静态方法只能访问静态的成员
🍭非静态方法可以访问静态的成员,也可以访问非静态的成员
🍭静态方法中是没有this关键字
代码实例
// static
public class Student {
private static int age; //静态的变量
private double score; //非静态的变量
public void run(){
}
public static void go(){
}
public static void main(String[] args) {
Student s = new Student();
System.out.println(Student.age);
System.out.println(s.score);
System.out.println(s.age);
s.run();
go();
}
}
public class Person {
//2.和对象同时产生,作用:赋初始值
{
System.out.println("匿名代码块");
}
// 1.只执行一次 类的加载而加载
static {
System.out.println("静态代码块");
}
//3
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
new Person();
System.out.println("----------------");
new Person();
}
}
package com.lxyk.oop6;
import static java.lang.Math.*;//静态导入包
/**
* @ClassName Test
* @Description TODO
* @Author FJQ
* @Date 2022/5/27 14:43
* @Version 1.0
**/
public class Test {
public static void main(String[] args) {
/* System.out.println(Math.random());
System.out.println(Math.PI);*/
System.out.println(random());
System.out.println(PI);
}
}
💥final关键字
👍fianl关键字的作用
💦final代表最终的意思,可以修饰成员方法,成员变量,类
👍final修饰类、方法、变量的效果
💦fianl修饰类:该类不能被继承(不能有子类,但是可以有父类)
💦final修饰方法:该方法不能被重写
💦final修饰变量:表明该变量是一个常量,不能再次赋值
🍭变量是基本类型,不能改变的是值
🍭变量是引用类型,不能改变的是地址值,但地址里面的内容是可以改变的
代码实例
public class Action extends Student {
}
public final class Student {
}
💥代码块
💠在Java中,使用 { } 括起来的代码被称为代码块
- 局部代码块
💠代码块的优先级
静态代码块>构造代码块>构造方法;
public class Person {
static{
System.out.println("1.我是静态块,优先于构造块执行!并且只有创建第一个对象的时候执行一次!");
}
{
System.out.println("2.我是构造块,优先于构造方法执行!每创建一个对象执行一次!");
}
public Person() {
System.out.println("3.我是构造方法,每创建一个对象执行一次");
}
public void function1(){
System.out.println("我是非静态方法中的普通代码块,方法被调用时执行!");
}
public static void function2(){
System.out.println("我是静态方法中的普通代码块,方法被调用时执行,晚于静态块执行!");
}
}
public class HelloWrold {
public static void main(String[] args) {
new Person().function1();
new Person().function2();
/*
* 我们可以看出:静态块总是最先执行的,并且只有在创建该类的第一个实例的时候才会执行一次;
* 第二执行的是构造块;第三执行的是构造方法。
* */
}
}
💥总结
非私有的成员方法和成员变量;
b、子类不能继承父类的构造方法,但是可以通过super关键字去访问父类的 构造方法
c、不要为了部分功能而去继承
1、this关键字和super关键字分别代表什么,以及他们各自的作用分别是什么?
this 关键字表示对象的引用,哪个对象来调用该类成员,就代表哪个对象
super 代表当前对象的父类的引用。
2、代码块是什么,分为哪几类,各自有什么特点?
代码块是用{}括起来的语句;
分类:根据位置和声明的不同分为以下几块:
1)局部代码块:在方法中出现,限定变量生命周期,及早释放,提高内存利用率;
2)构造代码块:又叫初始化块,
在类中方法外出现,多个构造方法中相同的代码存放到一起,每次调用构造方法都执行,
并且在构造方法前执行。
3)静态代码块:
* 在类中方法外出现,并加上static修饰符,用于给类进行初始化,在类加载的时候就执行,并且只执行一次;
一般用于加载驱动
4)同步代码块:
构造代码块,优先于构造方法执行,主要是为了提取构造方法中必须执行的公共代码!
构造代码块,每次创建对象时,都优先于构造方法执行!
作用:给构造方法进行初始化!
被static修饰的,随着类的加载而加载,静态代码块 随着类的加载而执行
静态代码块只执行一次
作用:用来加载特殊数据 比如:如果有些代码必须在项目启动的时候就执行,
需要使用静态代码块。
静态代码块,在虚拟机加载类的时候就会加载执行,而且只执行一次;
非静态代码块,在创建对象的时候(即new一个对象的时候)执行,
每次创建对象都会执行一次
相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,
一般在代码块中对一些static变量进行赋值。
不同点:静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。
静态代码块只在第一次类加载时执行一次,之后不再执行,而非静态代码块在每new
一次就执行一次。非静态代码块可在普通方法中定义(不过作用不大);而静态代码块不行。
总结:
局部代码块:在方法中出现
构造代码块:在类中方法外出现,随着对象的创建而加载,创建一次对象构造代码块执行一次
静态代码块:随着类的加载而加载,并且只执行一次(一般用于加载驱动)
主方法类中的静态代码块:优先于主方法执行
3、子父类都有静态代码块、构造代码块、构造方法,那么他们六者之间的执行流程是什么?
父类静态代码块
子类静态代码块
父类构造代码块
父类构造方法
子类构造代码块
子类构造方法
4、继承的好处、弊端分别是什么?
好处:提高代码的复用性
提高代码的维护性
让类与类之间产生关系,是多态的前提
弊端:类的耦合性增强了;
开发的原则是:高内聚,低耦合
耦合是类与类的关系
内聚是自己完成某件事的能力
5、Java中继承的特点是什么?
1)java中只支持单继承,不支持多继承(一个儿子只有一个亲爹)
2)java中支持"多层"继承,也就是继承体系。
6、Java中继承的注意事项是什么?我们什么时候使用继承?
a、子类只能继承父类所有
this 的作用:
1、this.成员变量:调用本类的成员变量,也可以调用父类的成员变量
2、this(...) 调用本类的构造方法;
3、this.成员方法:调用本类的成员方法,也可以调用父类的成员方法
super 的作用
1、super.成员变量:调用父类的成员变量
2、super(...) 调用父类的构造方法;
3、super.成员方法:调用父类的成员方法。
7、继承中构造方法的执行流程是什么?
先访问父类的构造方法,再访问子类的构造方法;
8、为什么子类中所有的构造方法默认都会访问父类的空参构造?
假如父类没有无参构造方法,子类应该怎么办?
1、因为子类继承父类中的数据,也可能会使用父类的数据;
2、子类初始化前,必须要要先将父类初始化。
如果父类没有空参构造,就用this或者super来调用父类的有参构造。
9、super关键字和this关键字可以在构造方法中共存吗?
this()或者super()都必须是在构造方法中的第一行;
❤️多态
🔷动态编译:类型:可扩展性(多态可以让可扩展性更强)
🔷即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
🔷一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
🔷多态存在的条件
💠有继承关系
💠子类重写父类
💠父类引用指向子类对象
🔷注意:多态是方法的多态,属性没有多态性。
🔷instanceof (类型转换)引用类型~
💥什么是多态
🔷生活中的多态
💠不同类型的打印机打印效果不同
🔷程序中的多态
💥如何实现多态
代码实例
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat() {
System.out.println("eat");
}
}
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
// new Student();
// new Person();
// 可以指向的引用类型 就不确定
// 当前事物是一个 学生
// Student能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
// 父类的引用指向子类对象
// 当前事物是一个 人
// Person:父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
s2.run(); //子类重写了父类的方法,执行子类的方法
s1.run();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
s1.eat();
//((Student) s2).eat();
/*
多态注意事项
1.多态的方法的多态,属性没有多态
2.父类和子类,有联系
3.多态的前提,要有继承关系,要有方法重写,要有父类引用指向子类对象!
*/
}
}
💥多态中的成员访问特点
🔷成员访问特点
成员变量 编译看父类,运行看父类
成员方法 编译看父类,运行看子类
代码实例
public class Fu {
int num = 10; // 成员变量
//成员方法
public void method(){
System.out.println("Fu.. method");
}
}
public class Zi extends Fu{
int num = 20;
public void method(){
System.out.println("Zi.. method");
}
}
public class Test {
/*
多态的成员访问特点:
成员变量: 编译看左边 (父类), 运行看左边 (父类)
成员方法: 编译看左边 (父类), 运行看右边 (子类)
*/
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);
f.method();
}
}
💥instanceof
🔷如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,
那么在转换的时候就会出现 ClassCastException
🔷解决方案
关键字instanceof
使用格式变量名 instanceof 类型
instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。
instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,
返回 boolean 的数据类型。
通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
代码实例
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person{
}
public class Teacher extends Person{
}
public class Action {
public static void main(String[] args) {
// Object > String
// Object > Person > Teacher
// Object > Person > Student
Object object = new Student();
System.out.println(object instanceof Student); // true
System.out.println(object instanceof Person); // true
System.out.println(object instanceof Object); // true
System.out.println(object instanceof Teacher); // false
System.out.println(object instanceof String); // false
System.out.println("-----------------------------------");
Person person = new Student();
System.out.println(person instanceof Student); // true
System.out.println(person instanceof Person); // true
System.out.println(person instanceof Object); // true
System.out.println(person instanceof Teacher); // false
//System.out.println(person instanceof String); // false //编译就报错
System.out.println("-----------------------------------");
Student student = new Student();
System.out.println(student instanceof Student); // true
System.out.println(student instanceof Person); // true
System.out.println(student instanceof Object); // true
//System.out.println(student instanceof Teacher); // false //编译就报错
//System.out.println(person instanceof String); // false //编译就报错
//System.out.println(X instanceof Y); //能不能编译通过 ! 看x和y有没有父子关系
}
}
💥多态中的转型
🔷向上转型
父类引用指向子类对象就是向上转型
🔷向下转型
格式:子类型 对象名 = (子类型)父类引用;
代码实例
class Fu {
public void show(){
System.out.println("Fu..show...");
}
}
class Zi extends Fu {
@Override
public void show() {
System.out.println("Zi..show...");
}
public void method(){
System.out.println("我是子类特有的方法, method");
}
}
public class Test3Polymorpic {
public static void main(String[] args) {
// 1. 向上转型 : 父类引用指向子类对象
Fu f = new Zi();
f.show();
// 多态的弊端: 不能调用子类特有的成员
// f.method();
// A: 直接创建子类对象
// B: 向下转型
// 2. 向下转型 : 从父类类型, 转换回子类类型
Zi z = (Zi) f;
z.method();
}
}
5、接口
🔷普通类:只有具体实现
🔷抽象类:具体实现和规范(抽象方法)都有!
🔷接口:只有规范!
🔷接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能...”的思想。
如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;
如果你是坏人,则必须欺负好人。
🔷接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
🔷OO的精髓,是对对象的抽象,最能体现这一点的就是接口。
为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、java、c#等),
就是因为设计模式所研究的,实际上就是如何合理的去抽象。
使用接口设计
防盗门功能
💥目标
- 掌握接口基础知识
- 掌握接口作为一种约定和能力的含义(重点,难点)
- 掌握面向接口编程(重点,难点)
💥为什么使用接口
问题?
我现在的需求是:要用java求实现防盗门的功能
分析:
门有“开”和“关”的功能,锁有“上锁”和“开锁”的功能,将门和锁分别定义为抽象类
思路:
将门定义为抽象类,锁定义为接口
防盗门继承门,实现锁的接口
防盗门可以继承门的同时又继承锁吗?
如何解决这个问题呢?
那我们java有没有什么办法和技术点解决这个问题嘛?
当然有,那就是我们今天要学习的新知识点,接口
💥什么是接口
语法
🔷1.认识一下接口
🔷2.接口的特性
接口不可以被实例化
实现类必须实现接口的所有方法
实现类可以实现多个接口
接口中的变量都是静态常量 :public static final
接口中所有的方法必须是抽象方法:public abstract
Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
💥如何使用接口
用程序描述USB接口
分析
USB接口本身没有实现任何功能
USB接口规定了数据传输的要求
USB接口可以被多种USB设备实现
可以使用Java接口来实现
编码实现
注意:(接口是java的多继承)
💥接口表示一种能力
做这项工作需要一个钳工(木匠/程序员)
接口是一种能力
面向接口编程
💥面向接口编程3-1
问题
实现防盗门功能
分析
💥面向接口编程3-2
实现过程
💥上代码(案列)
门:Door(抽象类)
public abstract class Door {
public abstract void open(); //开
public abstract void close(); //关
}
防盗门: TheftproofDoor(类)
public class TheftproofDoor extends Door implements Lock {
@Override
public void lockUp() {
System.out.println("插进钥匙,向左旋转钥匙三圈,锁上了,拔出钥匙。");
}
@Override
public void openLock() {
System.out.println("插进钥匙,向右旋转钥匙三圈,锁打开了,拔出钥匙。");
}
@Override
public void open() {
System.out.println("用力推,门打开了。");
}
@Override
public void close() {
System.out.println("轻轻拉门,门关上了。");
}
}
测试类:DoorTest
public class DoorTest {
public static void main(String[] args) {
//创建具体防盗对象
TheftproofDoor tfd = new TheftproofDoor();
tfd.close(); //关门
tfd.lockUp(); //锁门
tfd.openLock(); //开锁
tfd.open(); //开门
}
}
💥面向接口编程3-3
问题
扩展防盗门门铃功能,主要是实现拍照存档
💥学员操作:使用接口实现防盗门功能
需求说明:
使用面向接口编程实现防盗门的功能
💫开门、关门
💫上锁、开锁
💫拍照存档
防盗门实现门铃接口即可
测试类调用方法:takePictures();
💥小结
如何理解接口是一种能力?
代码实例
// 抽象的思维~java
// interface:定义的关键字, 接口都需要有实现类
public interface UserService {
//静态常量~ 一般不会在接口定义常量,只会定义方法
public static final int AGE = 99;
// 接口中的所有定义的方法 其实都是抽象的 public abstract
public abstract void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface TimeService {
void timer();
}
// 抽象类:extends~
// 类 可以实现接口 implements 接口
// 实现了接口的类,就需要重写接口中的方法~
// 多继承~利用接口实现多继承~
public class UserServiceImpl implements UserService,TimeService {
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
💥抽象类vs接口
💥面向对象设计原则
高耦合,低内聚
多用组合,少用继承针对接口编程针对扩展开放,针对改变关闭
阅读代码,找出错误
public interface MyInterface {
public MyInterface(); 错
public void method1(); 对
public void method2(){ } 错
private void method3(); 错
void method4(); 对
int method5(); 对
int TYPE = 1; 对
}
💥总结
6、内部类
💥内部类
🔷内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,
那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
🔷1.成员内部类
代码实例
public class Outer {
private int id = 10;
public void out() {
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
public class Action {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
🔷2.静态内部类
🔷3.局部内部类
代码实例
public class Outer {
//局部内部类(不建议这样玩)
public void method(){
class Inner{
public void run(){
System.out.println("局部内部类...");
}
}
Inner inner = new Inner();
inner.run();
}
}
//一个Java类中可以有多个class 类,但是只能有一个public class
class A{
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
}
}
🔷4.匿名内部类
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中!
new Apple().eat();
new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1111111");
}
}
interface UserService{
void hello();
}