一、概述
1.1 概念
面向过程适合处理简单的问题,面向对象采用分类思维模式,对于复杂的问题,为了从宏观上把握,从整体上合理分析,采用面向对象的思路来分析,具体到微观操作还是使用面向过程的方法来解决。
1.2 本质
以类的方式组织代码,以对象的形式封装数据。
二、方法
专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法。
格式:
Public 类名称(参数类型 参数名称){
方法体
}
注意事项:
- 构造方法的名称必须和所在的类名完全一样,包括大小写。
- 构造方法不要写返回值类型,连void都不写
- New对象的时候就是在调用构造方法。
- 构造方法不能return的具体返回值。
- 如果没有编写任何构造方法,那么编译器将会默认赠送一个,没有参数,方法体什么事情 都不做。一旦自己定义,编译器将不再赠送。
- 构造方法也是可以进行重载的。
构造方法的作用:
通过关键字new构造对象。当给对象的属性赋初始值时,可以用多个setter方法,也可以用构造方法一次性赋值。即,此时构造方法相当于多个setter方法。
三、对象
四、三大特性
面向对象语言的特性:封装,继承,抽象,多态。程序设计要追求:高内聚,低耦合
- 高内聚:类的内部数据操作细节自己完成
- 低耦合:仅仅暴露少量的方法给外部使用
4.1 封装
4.1.1 概念
数据的隐藏。通常,应禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问,这称为信息隐藏。
- 属性封装:当属性被private修饰时,只有在本类中才能随意直接访问。其它类无法通过任何方式调用,只有在定义该属性的内部提供对应的get/set方法,在其他类才可以对该属性进行操作。这样,在对类属性进行赋值时,在set方法中进行相关判断,避免问题出现。
- 方法封装:如果是一个方法被private修饰,那么只能在本类中通过类名调用
注:boolean方法的get方法名是is**,set方法定义规则不变*
4.1.2 特点
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护性增加
4.2 继承
4.2.1 概念
属性+方法=类,而类就是对对象的高度概括和抽取,而继承的本质就是对某一批类的抽象。继承是多态的前提,如果没有继承,就没有多态。继承主要解决的问题就是共性抽取。
4.2.2 特点
1.Java语言是单继承的。即,一个类的直接父类只能有一个。
2.可以多级继承。
3.一个父类可以有多个子类。
4. 如果父类的属性被private修饰,那么自子类是无法继承使用的。
4.2.3 继承中成员变量访问的特点
在父子类继承关系当中,如果成员变量重名的话,则创建子类对象时,访问同名成员变量有两规则:
- 直接通过子类对象访问成员变量:等号左边是谁就优先使用谁,没有则向上找
- 间接通过成员方法访问成员变量:方法属于谁,就优先使用谁,没有则向上找
4.2.4 继承中成员方法访问的特点
在父子类继承关系当中,如果成员方法重名的话,则创建子类对象时,访问同名成员方法的规则:
- 创建对象是谁,就优先用谁,没有则向上找
4.2.5 继承中方法的重写覆盖
在继承关系中,方法的名称一样,参数列表也一样
重写: Override–方法的名称一样,参数列表也一样。又叫覆盖、覆写
重载: Overload–方法的名称一样,参数列表不一样
特点: 创建的是子类对象,则优先使用子类方法
注解: 在类内要重写的方法前写@Override,表示这是一个该方法是重写的方法。该注解是可选参数,即只要满足重写方法的要求就算不写也认为重写方法。
注意事项:
- 方法的重写只限于非静态方法且只能被public修饰,因为静态方法在类加载时就已存在。所以就算是父类的引用指向子类,如果是静态方法,方法的调用只和左边的类型有关;如果是非静态方法,输出均为子类的结果
- 子类方法的返回值类型必须小于等于父类方法的返回值
- 子类方法的权限修饰符必须大于等于父类方法的权限修饰符
- 如果是static、final或者private修饰,均不可重写
方法的覆盖重写使用场景:
4.2.6 继承中构造方法的特点
- 子类构造方法当中有一个默认隐含的“super();”调用,所以一定是先调用父类的构造方法,后调用子类的构造方法
- 子类构造可以通过super关键字来调用父类的重载构造
- super的父类构造调用,必须是子类构造调用的第一条语句,即不能一个子类构造调用多次super构造
4.3 多态
4.3.1 概念
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。即同一个方法可以根据发送对象的不同而采用多种不同的行为方式。一个对象的实际类型是确定的(谁new的),但是左侧指向对象的引用类型可以有很多,因为会有不同的执行结果。
4.3.2 存在条件
- 有继承关系
- 子类重写父类方法,如果没有重写,调用时会向上找父类的方法
- 父类的引用指向子类对象
注:多态是方法的多态,属性没有多态
4.3.3 多态中成员变量和成员方法的使用规则
多态中成员变量和成员方法的使用规则与继承中使用方法相同
4.3.4 向上转型
向上转型一定是安全的,但是有一个弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。可通过向下转型【还原】来解决。
4.3.4 向下转型
对象的向下转型是一个还原操作,调用子类特有方法。
4.3.5 instanceof
格式:
对象 instanceof 类名称
会得到一个boolean值,也就是判断前面的对象本来是不是后面的类名称(实例)。
五、抽象类和接口
5.1抽象类
用abstract修饰符修饰的类叫抽象类,修饰的方法叫抽象方法。
5.1.1 注意事项
- 抽象类中可以没有抽象方法,但是有抽象方法的一定是抽象类
- 抽象类不能使用new关键字来创建对象,它是用来让子类继承的
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类来实现的
- 子类继承抽象类,就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
5.2接口
5.2.1 概述
代码中接口就是多个类的公共规范,且接口是一种引用数据类型,其中最重要的内容是抽象方法。
5.2.2 定义格式
Public interface 接口名称{//接口内容}
5.2.3 接口使用步骤
- 接口不能直接使用,必须有一个【实现类】来实现该接口
格式:
Public class 实现类名称 implements 接口名称{} - 接口的实现类必须覆盖重写所有的抽象方法
- 创建实现类的对象,进行使用
如果实现类没有将其中的抽象类全部重写,除非这个实现类也是抽象类。
5.2.4 说明
5.2.4.1 如果是java 7,那么接口中可以包含:
- 全局常量:public static final
- 抽象方法:public abstract
接口不能定义构造器,意味着接口不可以实例化,但是抽象类是有构造器的,当子类new的时候使用。对于接口,java中通过使用类来实现(implements)。如果实现类中覆盖重写了所有的抽象方法,则此实现类就可以实例化。Java类中可以实现多个接口,来弥补java单继承性的局限性。 接口和接口之间可以继承,并且可以多继承。实现类的集合叫做驱动
5.2.4.2 如果是java 8,包含:
- 默认方法
定义格式:
Public default 返回值类型 方法名称(参数列表){
方法体
}
使用方法:
(1)可以通过接口实现类对象,直接调用
(2)可以被接口实现类覆盖重写
注:
(1)默认方法会被实现类继承下去
(2)接口中的默认方法可以用来解决接口升级问题 - 静态方法
定义格式:
Public static 返回值类型 方法名称(参数列表){
方法体
}
使用方法:
(1)通过接口名称直接调用静态方法
注:
(1)不能通过接口实现类的对象来调用接口当中的静态方法,因为一个类可以实现多个接口,多个接口中静态方法可能会产生冲突
5.2.4.3 如果是java 9,包含:
- 私有方法
【背景描述】当多个默认方法之间存在重复代码的问题时,可以将其抽取成为一个单独的方法在内部被调用,但是该共有方法不应该被实现类使用,应该私有化。
【解决方法】
(1)普通私有方法,解决多个默认方法之间的重复代码问题
格式:
public 返回值类型 方法名称(参数列表){方法体}
(2)静态私有方法,解决多个静态方法之间的重复代码问题
格式:
public 返回值类型 方法名称(参数列表){方法体}
5.2.5 补充
接口当中可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。从效果上来看,这其实就是接口当中的常量。接口中的常量必须进行赋值,并且常量名称使用完全大写字母和_组成。
格式:
Public static final 数据类型 常量名称 = 数据值;
六、内部类
6.1 概述
如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类。
6.2 分类
- 成员内部类
【定义格式】
修饰符 class 外部类名称{
修饰符 class 内部类{
}
}
【使用方法】
(1)间接方式:在外部类的方法中,使用内部类,然后通过调用外部类的方法来间接调用内部类
(2)直接方式:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
【注意事项】
内用外,随意用;外用内,需要借助内部类对象 - 局部内部类
如果一个类是定义在一个方法的内部就是局部内部类。只在当前所属的方法中使用,超出该方法范围就不能使用了。
【格式】
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名(参数列表){
class 内部类名称{
…
}
}
…
}
【使用方法】
先在外部类方法中获取局部内部类的对象,通过该对象调用局部内部类的方法,在其他类中按照正常调用类中的方法的步骤调用外部类即可。
【注意事项】
局部内部类如果要访问所在方法的局部变量,那么这个局部变量必须是有效final.在java 8+,主要局部变量事实不变,那么final关键字可以省略不写。
原因:
New 出来的东西在堆内存中,而局部变量跟着方法走,在栈内存中,方法在运行结束后立即出栈,局部变量就会立刻消失,但是new出来的对象会在堆内存中持续存在,直到垃圾回收。 - 匿名内部类
如果接口的实现类,或者是父类的子类只需要使用唯一的一次,那么就可以省略掉该类的定义,改为使用匿名内部类。
【格式】
接口名称 对象名 = new 接口名称(){
//覆盖重写所有的抽象方法(匿名内部类的内容)
};
【注意事项】 - 匿名内部类在创建对象的时候只能使用唯一的一次。如果希望多次创建对象,而且类的内容一样的话,就必须单独定义实现类了。
- 匿名内部类是省略了实现类/子类,匿名对象是省略了对象名称。
任何一种类型都可以作为一种成员变量的类型
系列
Java(一):Java初识
Java(二):Java基础语法
Java(三):Java流程控制
Java(四):Java方法
Java(五):Java数组
Java关键字