面向对象编程
一、初识面向对象
1. 面向过程&面向对象
1.1面向过程思想(具体流程)
-
步骤清晰简单,第一步做什么,第二步做什么......(顺序、选择、循环结构)
-
面向过程适合处理一些较为简单的问题
1.2 面向对象思想(执行框架)
- 物以类聚,分类的思维,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个细分类下的细节进行面向过程的思索
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
- 属性+方法=类
- 对于复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到围观操作,仍然需要面向过程的思路去处理
2. 什么是面向对象
- 面向对象编程(Object-Oriented Programming——OOP)
- 面向对象编程的本质:以类的方式组织代码,以对象的方式组织(封装)数据※
- 抽象
- 抽取像的地方——剥离出共同点
- 例如学生管理系统——抽取学生身高,不用考虑其他的如年龄、胖瘦等
- 三大特性
- 封装——留一个接口(其他人可以用),将中间复杂的操作处理封装起来(其他人看不到)
- 继承——子类可以继承父类
- 多态——同一个事物可以表现出多种状态
- 从认识论角度考虑,
- 是先有对象后有类。对象是具体的事物,类是抽象的,是对对象的抽象
- 从代码运行角度
- 是现有类后有对象。类是对象的模板
二、方法回顾和加深
1. 方法的定义
-
修饰符
-
返回类型
package com.oop.demo01;
//Demo01 类
public class Demo01 {
//main 方法
public static void main(String[] args){
}
/*
修饰符 返回值类型 方法名(...){
//方法体
return 返回值
}
*/
public String sayHello(){
return "hello,world";
}
public int max(int a,int b){
return a>b ? a : b;//三元运算符
}
}
-
break和return的区别
- break跳出整个循环,即结束循环
- return结束方法,返回一个结果
-
方法名
-
注意规范
-
见名知意
-
包名——小写单数——scr
类名——首字母大写+驼峰原则——Demo01
方法、变量——首字母小写+驼峰原则——printArray(),isOrdered
常量——全大写字母+下划线——MAX_VALUE
-
-
-
参数列表
- (参数类型,参数名)
-
异常抛出
-
疑问、学习了面向对象才会了解
-
Arrayindexoutofbounds——数组下标越界
-
public void readFile(String file) throws IOException{ }
-
2. 方法的调用
2.1静态方法——static
- say方法可以通过类名Student直接调用

2.2 非静态方法——无static

-
非静态的方法可以调用非静态的,静态的方法可以调用静态的
- 但一个静态的方法不能直接调用非静态的
2.3 形参和实参
package com.oop.demo01;
public class Demo03 {
public static void main(String[] args) {
//法1. 先new实例化Demo03这个类才会加载非静态的add方法
/*
Demo03 demo03 = new Demo03();
int add = demo03.add(1,2)
*/
int add = new Demo03().add(1,2);
System.out.println(add);
//法2.改成静态的方法,add1方法是和Demo03类一起加载的,所以可以直接调用
int minus = add1(1,2);
}
//形参和实参类型要对应
public int add(int a,int b){
return a+b;
}
public static int add1(int a,int b){
return a+b;
}
}
2.4 值传递和引用传递※
值传递——java都是值传递
package com.oop.demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a = 1;
System.out.println(a);//1
Demo04.change(a);
System.out.println(a);//1,不是10
//把实参a传给了形参b,形参b的处理结果为b=10,但没有返回值给实参a
}
//返回值为空
public static void change(int b){
b = 10;
}
}
引用传递
- 类中的person.name修改的是内部类Person中属性name的值,String name默认值是null
- 对象不是八大基本类型,存的是地址,因此传递的是person的地址,地址是不变的,但地址的内容改变了
- 类中的无返回值的值传递,形参运算完是不会返回值给实参的
- int是基本类型,存的是值,形参和实参是两个不同的值
package com.oop.demo01;
//引用传递,对象,本质还是值传递
//需要理解对象、内层
public class Demo05 {
public static void main(String[] args) {
//实例化类Person的过程,创建了一个对象person,类型是Person
Person person = new Person();
//直接打印对象person的属性name的值
System.out.println(person.name);//null
//把对象person的属性name的值传给静态change1方法,再打印属性name的值
//Demo05.change1(person)和change1(person)效果一样
Demo05.change(person);
System.out.println(person.name);//秦疆——change方法没有返回值,但值改变了
}
//把对象person传进静态方法change中
public static void change(Person person){
person.name = "秦疆";
//静态类中的person.name修改的是内部类Person中属性name的值,String name默认值是null
//而无返回值的值传递,形参运算完是不会返回值给实参的
}
}
//内部类Person,有一个属性:name
class Person{
String name;//String默认值为null
}
2.5 this关键词
- 继承与多态
三、对象的创建分析※
1. 类和对象的关系
1.1 类是一种抽象的数据类型
- 它是对某一事物整体描述、定义,但是并不能代表某一具体的事物
- 动物、植物、手机、电脑
- Person类、Pet类、Car类
- 这些类都是用来描述/定义某一具体的事物应该具备的特点和行为
1.2 对象是抽象概念的具体实例
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念
- 张三就是人的一个具体实例
- 张三家里的旺财就是狗的一个具体实例
1.3 例子
- 只有一个类中含有main方法
- 在main方法中实例化其他类,获取对象,可以给类中的属性赋值
- 类——以类的方式组织代码
- 属性:一个抽象事物里的所有具体事物共有的特征,在main中实例化后赋值
- 方法:在main中实例化后调用
- 对象——以对象的形式封装数据
- 一个抽象事物里的所有具体事物
- 类——以类的方式组织代码

package com.oop.demo02;
//以类的方式组织代码
//学生类
public class Student {
//属性:字段
String name;
int age;
//方法
public void study(){
//this代表当前的类——Student
System.out.println(this.name+"再学习");
}
}
package com.oop.demo02;
//以对象的形式封装数据
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//类:抽象的,实例化——类是对象的模板,对象是类的实例
//类实例化后会返回一个自己的对象
//对象sutdent是类Student的一个具体的实例
Student student = new Student();
Student xiaoming = new Student();
Student xh = new Student();
xiaoming.name = "小明";
xiaoming.age = 3;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
System.out.println(xh.name);
System.out.println(xh.age);
}
}
/*
小明
3
null
0
*/
2. 创建与初始化对象※
2.1 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
2.2 构造器※
- 定义:类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的,并且构造器有以下两个特点
- 必须和类的名字相同
- 必须没有返回值类型,也不能写void
2.2.1 无参构造
-
非显式定义

- 在java的源文件——class文件中出现了一个默认的与类名Person相同的方法Person,且无返回值
- 一个类即使什么都不写也会存在一个方法
-
显示定义

2.2.2 有参构造

-
一旦定义了有参构造,无参就必须显示定义

2.2.3 构造器的作用
- new一个对象的本质是在调用构造器,因此用new关键字必须要有构造器
- 用来初始化对象中属性的值
2.2.4 如何使用idea快速创建构造器
- alt+insert--->alt+insert-->Constructor
- --->Select None 创建无参构造器
- 按住ctrl可以选择多个属性
2.2.5 如何用idea查看class文件


- 点击project,在out目录下即可找到java文件对应的class文件
- Idea不识别java文件的问题(类文件显示橙色)
2.2.6 小结
构造器:
1.和类名相同
2.没有返回值——无(返回)类型
作用
1.new本质是在调用构造器
2.初始化对象的值
注意点
1.定义有参构造之后,如果想要使用无参构造,显示的定义一个无参的构造
2.Alt+insert
3.this.属性 = 传进来的值
4.构造器可以重载,以参数的个数,类型,或排列顺序区分
2.3 堆、栈※
- 堆——存放new的对象和数组元素
- 栈——存放基本变量类型和引用变量,还有一些方法

2.3.1 Pet dog = new Pet();※
- 本质就是new在调用Pet构造(器/方法)
- 但Pet构造(器/方法)在方法区中,又不是静态方法,不能直接调用
- 先在堆中开辟了一个空间0x0002
- 然后用一个引用变量名dog表示对象,指向堆中的空间0x0002
- 因此new出的空间0x0002中初始不包括方法
- 方法是被调用时才创建的——空间中留了一个isa指针指向代码段
- 因此new出的空间0x0002中初始不包括方法
- 但Pet构造(器/方法)在方法区中,又不是静态方法,不能直接调用
- new了对象dog之后就可以调用Pet里的属性和方法了,或者改成静态的也能使用
3. 小结
- 类与对象
- 类是一个模板,对象是一个具体的实例
- 方法
- 定义、调用
- 对象的引用
- 八大基本类型
- 基本类型以外的都是引用类型
- 对象是通过引用来操作的
- 栈---->堆(地址)
- 对象的属性
- 字段field 成员变量——String name
- 默认初始化
- 数字——0 0.0
- char——u0000
- boolean——false
- 引用——null
- 修饰符 属性类型 属性名 = 属性值 —— Private Int age = 3;
- 对象的创建和使用※
- 必须使用new关键词创造对象,构造器 Person kuangshen = new Person();
- 对象的属性 kuangshen.name
- 对象的方法 kuangshen.sleep()
- 类
- 静态的属性
- 动态的行为
四、面向对象三大特性※
1. 封装
- 封装主要针对属性,而不是方法
- 属性私有,get/set
- 该露的露,该藏的藏
- 我们程序设计要求"高内聚,低耦合"
- 高内聚——类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合——仅暴露少量的方法给外部使用
- 我们程序设计要求"高内聚,低耦合"
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示
- 而应通过操作接口来访问,这称为信息隐藏
1.1 例子
- alt+insert--->Gatter and Setter 快捷输入get/set方法
package com.oop;
import com.oop.demo04.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("秦疆");
System.out.println(s1.getName());
s1.setAge(999);//不合法的
System.out.println(s1.getAge());
}
}
/*
秦疆
*/
package com.oop.demo04;
//类 private 私有
public class Student {
private String name; //名字
private int id; //学号
private char sex; //性别
private int age;
//提供一些可以操作这个属性的方法
//提供一些public的get、set方法
//get 获得这个数据
public String getName(){
return this.name;
}
//set 给这个数据设置值
public void setName(String name){
this.name = name;
}
public int getAge() {
return age;
}
//get/set可以添加一些判断进行封装,保护数据
public void setAge(int age) {
if (age<120||age>0) {
this.age = 3;
}else {
this.age = age;
}
}
}
1.2 封装的意义
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 提高系统可维护性
2. 继承
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
-
extends的意思是”扩展“。
-
子类是父类的扩展

-
-
Java中类只有单继承,没有多继承
- 一个儿子只有一个爸爸,但一个爸爸可以有多个儿子
-
继承是类和类之间的一种关系。
- 除此之外,类和类之间的关系还有依赖、组合、聚合等
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。
- 子类继承父类,使用关键词extends来表示
-
子类和父类之间,从意义上应该具有”is a“的关系
- Teacher is a Person
2.1 例子
- 子类继承父类的所有的非私有的方法和属性
main
package com.oop;
import com.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
System.out.println(student.money);
}
}
/*
说了一句话
1000000000
*/
父类
package com.oop.demo05;
//Person 人
public class Person {
//属性
public int money = 10_0000_0000;
//方法
public void say(){
System.out.println("说了一句话");
}
}
- 这里的父类中属性money用的public,但属性一般都会用private,然后用get/set方法调用,如下
private int money = 10_0000_0000;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
//相应的main中输出改成getMoney
System.out.println(student.getMoney());
子类
package com.oop.demo05;
//学生 is 人
public class Student extends Person{
//无参构造
}
2.2 object类
- ctrl+h 查看父子类关系

- Person类中没有任何方法,但在main中显示Person可以调用的方法

-
Java中,所有的类,都默认直接或间接继承object
-
所有显示定义也不会报错

-
2.3 super
- 子类的内部调用父类的方法和属性是通过super实现的
2.3.1 子类用super调用父类的属性
- super.name——调用父类的name属性

2.3.2 子类用super调用父类的方法
- super.print()——调用父类的print方法

- 需要在调用非静态的方法时需要加上 this. 增强逻辑性,避免思维混乱
2.3.3 私有的东西无法被继承
- 当将父类的public 方法改成private后,子类中用super也无法调用父类方法

2.3.4 子类默认调用了父类的无参构造

- new了对象student,先输出了父类Person的无参构造中的打印,再输出Student的无参构造中的打印
- 因此子类默认调用了父类的无参构造——super();

注意点
-
调用父类/子类构造器必须写在构造器的第一行
- super();——调用父类无参构造器

- this("哈哈")——调用本类的有参构造器
- super()也只能在第一行,所以会报错——super和this不能同时调用构造器

-
当类写了有参构造后必须写上无参构造
- 当父类写了有参构造后,无参构造就不会默认写了
- 子类也就调用不了父类的无参构造了,且子类根本无法写无参构造

- 因此当父类只有有参构造时,子类也只会继承有参构造,解决方法有一下三种
- 在父类写上无参构造
- 子类的构造器中用super(...);——去调用父类的有参构造。
- 子类的构造中用this();this(...)—— 调用本类的其他的构造方法,但是子类的其他的构造方法中一定会有一个去访问了父类的带参构造方法
- 当父类写了有参构造后,无参构造就不会默认写了


2.3.3 小结
- super注意点
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法中或者构造方法中
- super和this不能同时调用构造方法
- this对比
- 代表的对象不同
- this——本身调用者这个对象
- super——代表父类对象的引用
- 前提
- this——没有继承也可以使用
- super——只能在继承条件下才可以使用
- 构造方法
- this——本类的构造
- super——父类的构造
- 代表的对象不同
2.4 方法重写
- 封装主要针对方法,和属性无关
- 只与非静态方法有关
- 只能是public的方法
2.4.1 例子

- 去掉static后,Alt+Insert--->override

- 因此静态方法和非静态方法区别很大
2.4.2 小结
-
重载
- 同一类里
- 方法名相同,参数类型不同
-
重写
-
子父类之间(继承关系),子类重写父类的方法
-
方法名相同,参数类型相同,方法体不同(即方法的内容不同)
-
使用public方式,
-
且不能使用static
-
方法的修饰符:子类权限要比父类的宽松
- 父类protected 子类public
-
public>protected>Default>private
-
抛出异常:范围可以被缩小,但不能扩大:classNotFoundException --->Exception(大)
-
-
为什么需要重写
- 父类的功能,子类不一定需要,也不一定满足
-
重写的快捷键
- Alt+Insert--->override
3. 多态
- 动态编译:类型
- 即同一个方法可以根据发送对象的不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
- 多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类 对象
- 注意:多态是方法的多态,属性没有多态
- instanceof
3.1 例子
//父类Person 子类Student
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型不确定,可以是父类
//父类的引用指向子类的类型,父类引用子类的对象
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
}
}
- new的Student(),但是走的是Person的方法
- 子类继承所有父类的方法


- ((Student) s2).run();强制转换则可以
- 高---->低
- 如果子类和父类都有同一个方法
- 子类若没有重写,则调用父类的
- 子类重写,则调用子类的——在子类重写了父类的run方法

- 对象能执行哪些方法主要看对象左边的类型
- student里有run才能用
- person里没有run,而student里有run,那么s2.run()就不能用
- 子类指向的引用和父类指向的引用不一样
- student能调用的方法都是自己的或者继承父类的
- person可以指向子类,但是不能调用子类独有的方法
- 运行时和动态对象绑定
3.2 小结
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系 类型转换异常 classCastException
- 存在条件:
- 继承关系
- 方法需要重写
- 父类的引用指向子类对象
- 不能重写的方法
- static方法
- final 常量池
- private方法——不能被继承
- 构造器——不能被继承
3.3 instanceof
- 判断两个类之间是否存在父子关系
3.3.1 语法
boolean result = obj instanceof Class
-
obj 为一个对象,Class 表示一个类(或一个接口)
-
当 obj 为 Class 本类,子类或间接子类的对象时(或者是其接口的实现类)结果result 都返回 true,否则返回false。
-
//Person是父类 Student和Teacher是子类 Person person = new Student(); Object object = new Student(); //person(Student的对象)是Student的对象 person instanceof Student//true //person(Student的对象)是Person的子类的对象 person instanceof Person//true //person(Student的对象)是Object的间接子类的对象 person instanceof Object//true-
//person(Student的对象)与Teacher不是以上三者关系 //person是Person类型,Teacher是Person的子类,继承了Person类型 person instanceof Teacher//false //object(Student的对象)与String不是以上三者关系 //person是Object类型,String是Object的子类,继承了Object类型 object instanceof String//false
-
-
-
编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。
-
//person是Person类型,String是final类型,Person不能转换成final类型 person instanceof String//编译报错
-
3.3.2 例子
- 编译看做,运行看右
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extend Person {
public void go(){
System.out.println("go");
}
}
public class Teacher extend Person {
}
public class Application {
public static void main(String[] args) {
//编译看做,运行看右
Object object = new Student();
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Student);//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 Object);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Teacher);//False
System.out.println(person instanceof String);//编译报错
System.out.println("********************************");
Student student = new Student();
System.out.println(student instanceof Object);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Student);//true
// System.out.println(student instanceof Teacher);//编译报错
// System.out.println(student instanceof String);//编译报错
}
}
3.4 类型之间的转换
-
类型转换
-
自动转换——低---->高
-
Student obj = new Student(); Person obj = new Student();
-
-
强制转换——高---->低
-
Person obj = new Student(); //强制转换后就可以使用Student类型的方法了 ((Student)obj).run(); -
Student student = (Student)new Student(); student.run();
-
-
3.4.1 例子
- 子类强制转为父类可能会丢失方法
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person{
public void go(){
System.out.println("go");
}
}
public class Application {
public static void main(String[] args) {
Student student = (Student)new Student();
student.go();//编译通过
//自动转换——低---->高 子类---->父类
Person person = student;
person.go();//编译报错,引用不了子类Student自己的方法了
}
}
3.4.2 小结
- 父类的引用指向子类的对象
- 把子类转换为父类(向上转型),不用强制转换
- 子类转成父类后,就不能使用原本子类的方法了
- 把父类转换为子类(向下转型),强制转换
- 这样父类才可以调用子类的方法
- 方便方法的调用,减少重复代码,简洁
4. Static
4.1 静态属性
- 静态属性——推荐直接用类名调用,而不是使用对象调用
- 非静态属性——只能通过对象调用
public class Student {
private static int age;//静态变量
private double score;//非静态变量
public static int getAge() {
return age;
}
public static void setAge(int age) {
Student.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
//通过类Student调用getAge()方法
System.out.println(Student.getAge());
//age 静态属性——推荐直接用类名调用
//score 非静态属性不能通过类直接调用,只能通过对象调用
// System.out.println(Student.getScore());//编译报错
//通过类Student的对象s1调用getAge()方法
System.out.println(s1.getAge());//静态属性推荐直接用类名调用
System.out.println(s1.getScore());
}
4.2 静态方法
- 静态方法可以直接被非静态方法调用
- 静态方法可以用类直接调用
- 非静态方法只可以实例化后用对象调用
public class Student {
//非静态方法
public void run(){
go();
}
//静态方法
public static void go(){
new Student().run();
}
}
public class Application {
public static void main(String[] args) {
//调用静态方法
Student.go();
//非静态方法实例化后才能调用
Student student = new Student();
student.run();
//实例化写成这样也可以
// new Student().run();
}
}
4.3 静态代码块
- 静态代码块只执行一次
- 执行顺序
- 静态代码块>匿名代码块>构造器
- 匿名代码块
- 用于赋一些初始值
public class Person {
//2——赋一些初始值
{
//代码块(匿名代码块)
//在构造器之前,在创建对象时自动创建
System.out.println("匿名代码块");
}
//1
static{
//静态代码块
//类一加载直接执行,永久只执行一次
System.out.println("静态代码块");
}
//3
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("****************");
Person person2 = new Person();
}
}
/*
静态代码块
匿名代码块
构造方法
****************
匿名代码块
构造方法
*/
4.4 静态导入包
- 普通调用random方法要通过Math类
public class Test {
public static void main(String[] args) {
System.out.println(Math.random());
}
}
- 静态导入包后可以直接使用类Math下的random方法
import static java.lang.Math.PI;
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
System.out.println(random());//类Math下的方法
System.out.println(PI);//类Math下的常量
}
}
4.5 final修饰符
- 被final修饰的类,不会拥有子类
public final class Person {
}
//报错,因为Person被final修饰了
public class Student extends Person{
}
4.6 关于如何实现静态类
- Java不支持直接定义静态类,但可以定义静态内部类
五、抽象类和接口
1. 抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法,如果修饰类,那么就是抽象类
- 抽象类中没有抽象方法,但时有抽象方法的类一定要声明为抽象类
- 抽象类,不能使用new关键词来创建对象,他是用来让子类继承的
- 抽象方法,只有方法的声明,没有方法的实现,他是让子类实现的
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
1.1 例子
//abstract 抽象类
//extends 单继承 没法继承多个类,有局限性,因此继承用的不多
//但是接口可以多继承
public abstract class Action {
//约束——让其他人帮我们实现
//抽象方法——只有方法的名字,没有方法的实现
public abstract void doSomething();
}
//抽象类的所有方法,继承了它的子类都必须要实现它的抽象方法
public abstract class A extends Action{
//若子类也是抽象类,由子类的子类去实现
}
public class B extends A{
//若子类也是抽象类,由子类的子类去实现——重写父类的doSomething方法
@Override
public void doSomething() {
}
}
1.2 小结
-
抽象的抽象
-
不能new抽象类,只能靠子类去实现它——约束

-
一旦类中出现抽象方法,这个类必须声明为抽象类
- 但抽象类里可以写普通方法
1.3 思考题
1.3.1 抽象类不能new对象,那它存在构造器吗?
1.3.2 抽象类存在的意义是什么?
定义规范,提高开发效率
2.接口
- 普通类:只有具体实现
- 抽象类:具体和规范(抽象方法)都有
- 接口:只有规范
- 自己无法写方法,专业的约束
- 约束和实现分类
- 面向接口编程
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能…”的思想
- 如果你是天使,则必须能飞
- 如果你是汽车,则必须能跑
- 如果你是好人,则必须干掉坏人
- 如果你是坏人,则必须欺负好人
- 接口的本质时契约,就像我们人间的法律一样,制定好后大家都遵守
- OO的精髓,是对对象的抽象,最能体现这一点的就是接口,为什么我们讨论设计模式都只针对具备了抽象能力的语言(如C++、Java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
2.1 接口中方法的修饰符
- 默认都是public abstract

2.2 例子
- UserService接口
//抽象的思维
//interface 定义的关键字
//接口都要有实现类
public interface UserService {
//所有属性都是静态常量 public static final
//但一般接口不会写属性
int AGE = 99;
//所有定义发方法都是public abstract
void add(String name);//增
void delete(String name);//删
void update(String name);//改
void query(String name);//查
}
- TimeService接口
public interface TimeService {
void timer();
}
- 实现接口的类UserServiceImpl通过implements伪实现多继承
- 不能new
//抽象类 extends 单继承 有局限性——abstract class
//类可以实现接口 通过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() {
}
}
2.3 接口的作用
- 约束
- 定义一些方法,让不同的人实现 10----->1
- 方法都是public abstract
- 属性都是public static final
- 接口不能被实例化,接口中没有构造方法
- implements可以实现多个接口
- 必须要重写接口中的方法
六、内部类及OOP实战
1. 内部类
-
内部类就是一个类的内部再定义一个类
- 比如,A类中定义一个B类,那么B类相对A类来说就称为内部类
- 而A类相对B类来说就是外部类了
-
成员内部类
-
静态内部类
-
局部内部类
-
匿名内部类
1.1 成员内部类
//外部类
public class Outer {
private int id;
public void out(){
System.out.println("这是外部类的方法");
}
//内部类
public class Inner {
public void in(){
System.out.println("这是内部类的方法");
}
}
}
import com.oop.demo10.Outer;
public class Application {
public static void main(String[] args) {
//实例化外部类Outer
Outer outer = new Outer();
//实例化内部类inner——通过外部类实例化内部类
Outer.Inner inner = outer.new Inner();
//调用内部类的方法
inner.in();
}
}
/*
这是内部类的方法
*/
- 内部类还可以访问外部类的private变量
//外部类
public class Outer {
private int id=10;
//内部类
public class Inner {
public void getId(id){
System.out.println(id);
}
}
}
import com.oop.demo10.Outer;
public class Application {
public static void main(String[] args) {
//实例化外部类Outer
Outer outer = new Outer();
//实例化内部类inner——通过外部类实例化内部类
Outer.Inner inner = outer.new Inner();
//调用内部类的方法
inner.getId();
}
}
/*
10
*/
1.2 静态内部类
- 当上面这个例子里的内部类变成static后,编译报错
- 因为在加载外部类前要先加载static的内部类
1.3 匿名内部类
public class Test {
public static void main(String[] args) {
//正常实例化对象
// Apple apple = new Apple();
//没有名字初始化类——不用将实例保存到变量中
new Apple().eat();
//没有名字等同于
//UserServise userServise = new UserServise(){}
//相当于调用接口
new UserServise(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserServise{
void hello();
}
1.4 局部内部类
//外部类
public class Outer {
//外部类的方法
public void method(){
//局部内部类
class Inner{
//内部类的方法
public void in(){
}
}
}
}

浙公网安备 33010602011771号