- 面向对象
- 面向对象3大特性
- java面向对象
- 3大特性在java中的体现
- java中的对象相关的关键字
- final 修饰符
- 语义
- 区分 final修饰成员变量 和局部变量
- 区分final修饰基本类型变量 和 修饰引用类型变量
- final方法
- final类
- 不可变类
- 缓存不可变类的实例 TODO实现
- 抽象类
- 适用 的场景
- 规则
- 抽象类 与 抽象方法
- 更彻底的抽象 接口
- 接口与抽象类的区别和联系
- 区别
- 联系
- 内部类
- 内部类的作用
- 非静态内部类
- 静态内部类
- 局部内部类
- 匿名内部类
- 使用内部类
- 闭包 与 回调
- 闭包
- 回调
面向对象
面向对象3大特性
封装
继承
多态
图片参考:如何用一句话说明什么是面向对象思想?
java面向对象
3大特性在java中的体现
【封装】 : java提供了private,protected,和public 3个访问控制修饰符。
【继承】 : 提供了extends关键字让子类继承父类。
【多态】:子类对象 可直接赋值给 父类变量。
java中的对象相关的关键字
final 修饰符
语义:
final修饰的变量获得初始值后不能被重新赋值。
区分 final修饰成员变量 和局部变量
【final 修饰成员变量】
(1)final修饰的成员变量必须由程序员显示的初始化,系统不会对final成员进行隐式初始化。 (与普通成员变量不同的是)(2)final修饰的类变量在声明时或静态初始化块中指定初始值。
(3)final修饰的实例变量,在声明时或非静态初始化块中或构造器中指定初始值;
正确写法:
class A{
final int data = 0;//正确
}
错误写法:
class A{
final int data;//错误
}
【final修饰的局部变量】
系统不会对局部变量进行初始化,局部变量必须由程序员显示初始化。因此使用final修饰局部变量时,(1)既可以在定义时指定默认值,也可以不指定默认值。(2)如果final 修饰的局部变量在定义时没指定默认值,则可以在后面的代码中对该fianl变量赋初始值,但只能一次,不能重复赋值。
正确写法:
public static void main(String[] args) {
final int data = 2;
System.out.println(data);
}
或者:
public static void main(String[] args) {
final int data ;
data = 2;
System.out.println(data);
}
错误写法1:
public static void main(String[] args) {
final int data;
System.out.println(data);//报错,使用之前未初始化data.(如果不使用,则不会报错)。该阶段由编译器检查。
}
错误写法2:
public static void main(String[] args) {
final int data ;
data = 2;
data = 3; // 编译时报错,只能赋值一次。
System.out.println(data);
}
另外局部变量(无final 修饰情况)也必须被初始化:
public static void main(String[] args) {
int data ;
System.out.println(data);//报错
}
区分:final修饰基本类型变量 和 修饰引用类型变量
【final修饰基本类型变量】,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。
【final 修饰 引用类型变量】,它保存的仅仅是一个引用,final只保证这个引用类型变量所引用的地址不变,即一直引用同一个对象(使用final修饰的引用类型变量不能被重新赋值),但这个对象完全额可以发生改变(即可以改变引用类型变量所引用对象的内容)。
final方法
final修饰的方法不可被重写。如果不希望子类重写某个方法,可以使用final修饰该方法。
final类
final类不可以有子类(不可被继承)。
如:String类。
不可变类
使用private和final修饰符类修饰该类的成员变量。
提供带参数构造器
不提供setter方法
如果有必要,重写Objcet类的hashCode()和equals()方法。
缓存不可变类的实例 (TODO:实现)
如果程序经常需要使用相同的不可变类实例,则应该考虑缓存者在不可变类的实例。毕竟重复创建相同的对象没有太大的意义,而且加大系统开销。
抽象类
适用 的场景
某个父类 知道 子类 应该包含怎样的方法,但无法确切知道子类如何实现。
【举例】比如,父类 车能够行走(walk()),但是我们不能说明如何行走,只能在子类中去具体化,子类 汽车用轮子行走。
更具体的作用:
抽象类是从多个具体类抽象出来的父类,具有更高的抽象层次。
抽象类一般作为子类的模板,从而避免了子类设计 的随意性。
了解更多内容可参看模板模式:【菜鸟教程】模板模式
规则
关键字:
修饰对象: (1)类 ;(2)方法。
抽象类
abstract class Animal { //用abstract来定义一个Animal为抽象类
}
抽象方法
public abstract void go(); //用abstract来定义一个抽象方法 go.
抽象类 与 抽象方法
必须使用修饰符 abstract。
抽象方法不能有方法体。
抽象类不能被实例化。( 无法使用new关键字来创建实例 )
【抽象类可包含成分】: Field、方法(普通方法及抽象方法)、构造器、初始化块、内部类、枚举类。
【抽象方法 与 抽象类关系】抽象方法只能被定义成抽象类。
注意:
【矛盾修饰】 static 与 abstract不能同时修饰方法。static方法是类的方法,没有所谓的类抽象方法。
【矛盾修饰】private 与 abstract不能同时修饰方法。abstract修饰的方法必须被子类重写才有意义,而private则是拒绝子类重写,产生矛盾。所以不能同时修饰。
【区分:空方法 与抽象方法】
空方法:
public void test(){}
抽象方法:
public void test();//没有方法体。
更彻底的抽象 : 接口
【主要思想】接口是从多个相似类中抽象出来的规范,接口不提供任何实现.接口体现的是规范和实现分离的哲学.
接口通常是定义多一组公用方法.
接口与抽象类的区别和联系
区别
参考:(接口与抽象类的区别)
1.【继承角度】一个类可以实现多个接口 ,但却只能继承最多一个抽象类。
2.【抽象方法的纯粹性】抽象类可以包含具体的方法 , 接口的所有方法都是抽象的。
3.【成员变量的限制】抽象类可以声明和使用字段 ,接口则不能,但接口可以创建静态的final常量。
4.【方法的权限】接口的方法都是public的,抽象类的方法可以是public,protected,private或者默认的package;
5.【构造函数】抽象类可以定义构造函数,接口却不能。
6.【适用的场景的区别】(1)接口体现的是纯粹的规范(全为抽象方法)、标准(类似数据库中的模式);(2)抽象类,体现了模板设计,是实现过程中的中间产品。(介于高度抽象的规范 与 具体实现之间的一种中间形式)
PS: 体会面向接口的设计思想。
联系
【实例化】接口与抽象类都不能被实例化。
【抽象方法】都可以包含抽象方法。
内部类
内部类 (嵌套类): 一个类的定义 放在另一个类中。
内部类的作用
【增强封装】 内部类提供了更好的封装, 可以把内部类隐藏在其外部类之内。外部类可控制外界对于内部类的访问。(例如:Cow类,需要组合一个CowLeg对象,而CowLeg只在Cow类中有效,这时就可以用内部类)
【内部类的权限】内部类可直接访问外部类的私有数据。但是,外部类不能访问内部类的一些实现细节。
【匿名内部类】适合于创建哪些仅需要一次使用的类。(如实现匿名监听器类)
非静态内部类
内部类属于某个对象
定义形式:
public class Cow{
private class CowLeg{//非静态内部类
}
}
静态内部类
该内部类属于外部类本身,而不是外部类的某个对象。
定义形式:
public class Cow{
static class CowLeg{//非静态内部类
}
}
局部内部类
如果把一个内部类放在方法中定义,则该类为局部内部类。
【作用范围】仅在该方法中有效。因为局部内部类不能在除方法之外的地方使用,所以局部内部类不能使用 访问控制符 和static 修饰符修饰。
【注意】一个类中可以有重名的局部内部类(在不同的方法中)。
举例:
public static void main(String[] args) {
class CowLeg{ //定义局部内部类
}
Cowleg cl = new CowLeg(); //使用局部内部类
}
匿名内部类
创建只需要使用一次的类,(使用该类创建一次实例)。
注意:
不能为抽象类。
不能定义构造器。(因其没有类名,但可定义实例初始化块,通过这种形式完成构造器要做的事情)
定义形式:
new 父类构造器(实参列表)| 实现接口(){
//匿名内部类类体部分
}
使用内部类
(1)在外部类内部 使用 内部类
和普通类的使用没有什么区别。唯一的区别是:不要在外部类的静态成员中使用非静态内部类,因为静态成员不能访问非静态成员。
访问形式:
Cowleg cl = new CowLeg(); //在外部类内部使用 内部类
(2)在外部类以外 使用 非静态内部类
权限角度:
【使用private修饰的内部类】不能用private修饰内部类。(private修饰的内部类只能在外部类内部中使用)
【省略访问控制符的内部类】只能被 与外部类处于同一个包中 的其他类访问。
【使用protected修饰的内部类】可访问者为:(1)与外部类处于同一个包中的其他类;(2)外部类的子类。
【使用public修饰的内部类】任何地方均可访问。
使用形式:
public class Cow{
public class CowLeg{//非静态内部类
}
}
在Cow外部访问 CowLeg:
Cow cow = new Cow();
Cow.CowLeg cl = cow.new CowLeg(); // 依赖于Cow的实例。
(3)在外部类以外使用静态内部类
静态内部类 是 外部类类相关的, 因此创建内部类对象时 无需 创建外部类对象。
使用形式:
public class Cow{
static class CowLeg{//非静态内部类
}
}
在Cow外部使用CowLeg:
Cow.CowLeg cl = new Cow.CowLeg();
闭包 与 回调
闭包
闭包是一种能被调用的对象,它保存了创建它的作用域信息。
回调
允许客户类通过 内部类引用 来调用 其外部类的方法。
闭包 为回调 提供了基础。
注意:
监听器模式,可以把监听器定义在被监听 的内部,就很好的体现了闭包与回调的思想。