-
OOP(Object-Oriented Programming)------面向对象编程
-
一个项目应该只存在一个main方法
面向对象
-
从认识论角度考虑是先有对象后有类,对象:具体的事物;类:抽象的,是对对象的抽象
-
从代码运行角度考虑,是先有类后有对象,类是对象的模板
面向对象思想
-
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考,最后才对某个分类下的细节进行面向过程的思考
-
面向对象适合处理复杂的问题,适合处理需要多人合作的问题
-
对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思想来分析整个系统,但是,具体到微观操作,仍然需要面向过程的思路去处理
本质
-
以类的方式组织代码,以对象的形式封装数据
核心思想
-
抽象
三大特性
-
封装
-
继承
-
多态
封装
定义
-
高内聚、低耦合
-
高内聚:类的内部数据操作细节由自身完成
-
低耦合:仅暴露少量的方法给外部使用
-
-
封装就是数据的隐藏:禁止直接访问一个对象中数据的实际表示,应通过操作接口来访问,也称为信息隐藏
-
实际操作是用private访问修饰符修饰属性
-
使得不能直接调用该累的属性,变为私有的
-
-
封装的本质就是属性私有,访问通过getter/setter方法进行
优点
-
良好的封装能够减少耦合。
-
类内部的结构可以自由修改。
-
可以对成员变量进行更精确的控制。
-
隐藏信息,实现细节
继承
快捷键:ctrl+h------打开继承树
定义
-
继承是Java面向对象编程技术的一块基石,它允许了创建分等级层次的类
-
继承就是子类继承父类的特征和行为,是的子类对象具有父类的实例域和方法,或子类继承父类的方法,使得子类具有和父类一样的行为
-
继承需要的符合的关系是is- a,父类更通用,子类更加具体
-
本质上是对某一批类的抽象,使得可以更好地对现实世界建模
-
继承是Java中类与类之间的一种关系,除此之外还有依赖、组合、聚合
继承的格式
-
extends是“扩展” 的意思,表示子类是父类的扩展,也叫做派生类
-
在Java中通过使用extends关键字,表明一个类是从另一个类继承过来的:
class father{ } class son extends father{ }
继承的类型
-
继承只有单继承,没有多继承,但是支持多重继承
继承的特点及优点
特点
-
子类拥有父类非 private 的属性、方法
-
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
-
子类可以用自己的方式实现父类的方法。
-
Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
-
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
-
当父类拥有有参构造,默认无参构造自动消失,且当子类继承父类,也无法拥有无参构造
-
所以所有类一旦定义了有参构造,如果想要调用无参构造,无参构造必须要显示定义
-
即定义有参构造就是对默认无参构造的重载,若不重新显示定义无参构造,就只有有参构造可以被调用
-
优点
-
减少重复的代码
-
维护性也提高
-
代码也更加简洁
-
提高代码的复用性
Object类
-
在Java中,所有的类都直接或间接的继承Object类
Super与This关键字
-
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
-
只能在继承条件下才可以使用
-
但并不能访问私有的父类属性或方法
-
调用父类的构造器:super();---若没有显示调用,也会默认隐式调用方法;且调用父类的构造器,必须只能出现在子类的方法或构造方法中,且必须要在子类构造器的第一行,且只会调用无参构造,想调用有参构造需要在()内加上参数
-
调用本类的构造方法:this();---同样要放在本类构造器的第一行,两者不可同时调用构造方法
-
-
this关键字:指向自己的引用,及实现对本类属性的访问
-
在没有继承的情况下也可以使用
-
方法的重写和重载
-
重写与重载都是针对方法的形式,和属性无关
重写(override)
-
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写
-
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常
-
重写只和非静态的方法有关
为什么重写
-
父类的功能,子类不一定需要,或子类不一定满足
重写的规则
-
参数列表与被重写方法的参数列表必须完全相同。
-
返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
-
访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
-
父类的成员方法只能被它的子类重写。
-
声明为 final 的方法不能被重写。
-
声明为 static 的方法不能被重写,但是能够被再次声明。
-
子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
-
子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
-
重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
-
构造方法不能被重写。
-
如果不能继承一个类,则不能重写该类的方法
super关键字对重写的使用
-
当需要在子类中调用父类的被重写方法时,要使用 super 关键字
-
调用父类中那个被重写前的方法
重载
-
重载(overloading) 是在一个类里面,方法名相同,而参数不同。返回类型可以相同也可以不同。
-
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
-
最常用 是构造器的重载
重载的规则
-
被重载的方法必须改变参数列表(参数个数或类型不一样);
-
被重载的方法可以改变返回类型;
-
被重载的方法可以改变访问修饰符;
-
被重载的方法可以声明新的或更广的检查异常;
-
方法能够在同一个类中或者在一个子类中被重载。
-
无法以返回值类型作为重载函数的区分标准。
总结
-
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
-
方法重载是 一个类 中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
-
方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
-
方法一个类的多态性表现,而方法重写是子类与父类的一种多态性表现
-
多态
-
多态是方法的多态,和属性无关
-
是同一个方法可以根据发送对象的不同而采用多种不同的行为方式
-
一个对象的实际类型是确定的,但可以指向的引用类型不确定:例如父类引用指向子类对象或有关系的类引用
定义
-
同一个行为具有不同表现形式或形态的能力
-
是同一个接口,使用不同的实例而执行不同操作
-
多态性是对象多种表现形式的体现
-
当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法
-
要想调用父类中被重写的方法,则必须使用关键字 super
优点
-
消除类型之间的耦合关系
-
可替换性
-
可扩充性
-
接口性
-
灵活性
-
简化性
多态存在的三个必要条件
-
继承
-
重写
-
父类引用指向子类对象:Parent p = new Child();
多态的实现方式
方法一:继承
方法二:重写
-
生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
-
java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。
-
不可重写的方法:
-
static修饰的方法,属于类,不属于实例,无法被重写
-
final修饰的方法,属于常量,不可改变,无法被重写
-
private修饰的方法,属于私有方法,无法被继承,也就无法被重写
-
方式三:抽象类和抽象方法
类型转换
-
前提是继承,才可以父子间相互转换 类型转换异常:ClassCastException
-
一个对象的实际类型是确定的,但可以指向的引用类型不确定:例如父类引用指向子类对象
-
对象能执行什么方法,主要看对象左边的类型,和右边的关系不大
-
可以方便方法的调用,减少重复的代码
向上转型:父类引用指向子类对象
Father father = new Son(); //或 Son son = new Son(); Father father = son;
-
使用父类类型的引用指向子类的对象
-
该引用只能调用父类中所有的属性和方法,不能调用子类独有的方法
-
如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法
-
变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错
-
不需要强转
向下转型:将父类强制转换为子类
Father father = new Son(); Son son = (Son)father; //或 ((Son)father).方法或属性
-
将father对象转换为Son类型之后,才能使用Son类型中的方法和属性
-
需要强转
inistanceof关键字
father inistanceof Son
-
使用次关键字比较的前提是关键字两边的具有一定关系:例如父子关系
-
测试它左边的对象是否是它右边的类的实例,测试左边对象是否是右边类的子类或本类,返回 boolean 的数据类型
static关键字详解
-
static关键字修饰的方法或属性,都存放在静态方法区内
-
可以直接使用类名来调用,无需创建对象(若存在static修饰的方法或变量,建议使用类名直接调用)
-
在本类中可以直接调用,无需包名或对象名
-
在其他包中使用,需要导包后调用
静态方法
-
static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量
静态变量
-
static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。
静态代码块
static{ //静态代码块 }
静态导入包
import static java.lang.Math.Random; //可以直接调用包中的方法
-
在类加载后执行,且只执行一次(创建多个对象也是一样只执行一次),在匿名代码块与构造方法之前
final 修饰符
修饰规则
-
用来修饰类、方法和变量,final修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的
-
被 final 修饰的实例变量必须显式指定初始值
-
final 修饰符通常和 static 修饰符一起使用来创建类常量
-
声明 final 方法的主要目的是防止该方法的内容被修改
-
类与对象的关系
-
类是一种抽象的数据类型,它是对某一类事物整体描述与定义,但是并不能代表一个具体的事
-
对象就是抽象概念的具体实现(实例)
类
-
类是抽象的
-
类由属性和方法组成
-
每个类都要有构造方法,即使什么也不写也会存在一个默认的无参构造方法
-
类是实例化之后会返回一个自己的对象,但用new关键字时,必须要有构造器,本质就是调用构造器
-
一个Java类中可以有多个class类,但只能有一个public class
public class A{ } class B{ //可以在此类中建立main方法测试 public static void main(String[] args) { } }
匿名代码块
{ //匿名代码块 } //对象创建后在构造方法前自动调用 //作用:可以赋初始值
抽象类
abstract 修饰符
-
abstract修饰符可以修饰类或方法,分别为抽象类与抽象方法
public abstract class abstractDemo { public abstract void test(); }
规则
-
目的是为了将来对该类进行扩充
-
一个类不能同时被 abstract 和 final 修饰
-
如果一个类包含抽象方法,那么该类一定要声明为抽象类
-
抽象类可以包含抽象方法和非抽象方法
-
抽象类不可以使用new关键字来创建对象,是用来被子类继承的
-
抽象方法只有声明,没有方法的实现,且不能被声明成 final 和 static,是用来让子类实现的
-
任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类
-
相似的有接口,在下面
内部类
-
在一个类的内部在定义一个类:A类中定义了一个B类,B类相对于A类就是内部类,A类相对于B类就是外部类
-
内部类的实例化需要通过外部类来进行
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();
成员内部类
//外部类 public class Outer{ //成员内部类 public class Inner{ } }
-
成员内部类可以直接获得外部内的私有属性和方法
静态内部类
//外部类 public class Outer{ //静态内部类 public static class Inner{ } }
-
不能直接获取外部类的非静态的私有属性和方法
局部内部类
//外部类 public class Outer{ //局部内部类 public void method(){ class Inner{ } } }
-
与局部变量相似?
匿名内部类
public class A{ new B().eat(); new UserService{ @override public void drink(){ }; } } class B{ public void eat(){ } } interface UserService{ public void drink(); }
-
没有名字初始化,不用将实例保存到变量中
对象
对象的创建
-
使用new关键字创建对象
-
声明:声明一个对象,包括对象名称和对象类型。
-
实例化:使用关键字 new 来创建一个对象。
-
初始化:使用 new 创建对象时,会调用构造方法初始化对象
-
类名 对象名 = new 初始化对象(构造方法)
-
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
对象的使用
-
对象的属性以及方法都是通过对象名.属性名或方法名
-
对象能执行什么方法,主要看对象左边的类型,和右边的关系不大
对象的引用
-
对象是通过引用来操作的
-
引用就是一个只想对象的地址
对象的属性
-
属性也叫做字段Field,或者成员变量
-
不定义属性会自动默认初始化
-
数字类型默认0
-
char类型默认 u0000
-
boolean类型默认 false
-
引用类型默认为 null
-
-
语法:修饰符 属性类型 属性名 = 属性值
-
一般不初始化属性值
-
修饰符默认为default
-
构造方法
-
类中的构造器也称为构造方法,是在进行创建对象时必须要调用的
-
构造器必须和类的名字相同
-
必须没有返回类型,也不能写void
-
new对象时调用构造方法,所以构造器是new对象时必须存在的
-
一旦定义了有参构造,如果想要调用无参构造,无参构造必须要显示定义
-
每个类都要有构造方法,即使什么也不写也会存在一个默认的无参构造方法
-
构造器的本质就是初始化对象的值
-
有参构造就是重载了无参构造
-
构造方法可以存在多个,但参数必须不同
-
idea构造方法快捷键:alt+insert
-
//无参构造 public 类名(){ } //有参构造 public 类名(参数类型 参数名,.....){ this.参数名 = 参数名; //this.参数名表示类的属性 }
-
是必须掌握且每创建类时第一时间应该建立的方法
接口
-
普通类:只有具体实现
-
抽象类:有具体实现和规范(抽象方法)
-
接口:只有规范,无法具体实现方法------专业的约束:也是就约束和实现分离:面向接口编程
定义
-
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
-
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
-
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
-
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类
-
在接口中定义的属性都是常量,一旦定义就默认是一个静态常量:
public static final 数据类型 属性名 = 值; //通常不在接口中这样定义
[可见度] interface 接口名称 [extends 其他的接口名] { // 声明变量 // 抽象方法 public abstract 返回值 方法名(参数类型 参数名); //建议直接:返回值 方法名(参数类型 参数名); }
接口与类的相似点
-
一个接口可以有多个方法。
-
接口文件保存在 .java 结尾的文件中,文件名使用接口名。
-
接口的字节码文件保存在 .class 结尾的文件中。
-
接口相应的字节码文件必须在与包名称相匹配的目录结构中
接口与类的区别
-
接口不能用于实例化对象。
-
接口没有构造方法。
-
接口中所有的方法必须是抽象方法
-
Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
-
接口不能包含成员变量,除了 static 和 final 变量。
-
接口不是被类继承了,而是要被类实现。
-
接口支持多继承。
接口特性
-
接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
-
接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
-
接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法
-
接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
-
接口中的方法都是公有的。
抽象类和接口的区别
-
抽象类中的方法可以有方法体,就是能实现个接口的时候,不必使用abstract关键字。
-
接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
-
抽象类可以编写方法的具体功能,但是接口中的方法不行。
-
抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是 public static final 类型的。
-
接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
-
一个类只能继承一个抽象类,而一个类却可以实现多个接口
接口的实现
-
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
-
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面
访问修饰符 class 类名 implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ... //ctrl+i:快捷实现接口内的方法在类中创建