包装类
- 8种基本类型不同于对象,没有成员变量和方法可以调用,在内存中也能存储在任何地方,包括栈内存、堆内存
- 之所以提供这八种类型,是为了以及储存方便,也可能是照顾程序员的习惯
- 8种基本类型都有各自对应的对象类型
- 基本类型可以自动转变为对象类型,称为自动装箱
Integer i = 123
- 相反的过程称为自动拆箱
int i = new Integer(123)
- 包装类可以与基本类型直接比较
Integer i == 123; i == 123; 返回true
- 考虑如下情况
Integer i1 = 12;
Integer i2 = 12;
i1 == i2; //返回true
Integer i1 = 1234;
Integer i2 = 1234;
i1 == i2; //返回false
- 原因:Java对-127到128之间的数字使用缓存,该范围内不同的Integer引用同一个对象,如果超出这个范围,就会创建一个新的Integer对象
- 不推荐使用==, 应该使用包装类的compare方法比较两个包装类对象
==和equals
-
对基本类型,只能用==,无需类型相同,只要数值相同即可
'A'==65,返回true
-
String类型的==比较的是内存地址,与Java的String初始化机制有关
s1 = "黄晓明"
s2 = "黄" + "晓明"
s3 = "黄", s4 ="晓明", s5 = s3 + s4
s6 = new String("黄晓明")
s1 == s2,输出true
s1 == s5,输出false
s1 == s6,输出false
单例模式
- 对有些类,希望只存在一个实例,例如dota中的Roushan只有一个
要点:private static本类实例变量、private构造器、public方法获取单例
public class Roushan {
//将本类对象设为私有成员变量
private static Roushan instance;
private int hp = 10000;
private int damage = 100;
//私有化构造器,使外界不能构造对象
private Roushan() {
}
//公开方法获取唯一的对象
public static Roushan getInstance() {
if (null == instance) {
instance = new Roushan();
}
return instance;
}
public static void main(String[] args) {
//调用类方法获取单例对象
Roushan roushan = Roushan.getInstance();
}
}
final修饰符
-
final变量必须显式定义初始值,否则无法通过编译,系统不会自动初始化为0或者null
-
final类变量,只能以下之一中显式定义初始值:
- 初始化时
- 静态初始化块中
-
final实例变量,只能在以下之一中显式定义初始值
- 初始化时
- 普通初始化块
- 构造器中
-
final形参
- 在值传递时直接赋值,方法体中不能再修改
-
final局部变量,方法体中赋值后不能再修改
-
final方法
- private final方法可以在子类中重新定义,但不属于重写
- public final方法不能在子类中重写,编译出错
-
final类
- final类不可被继承
-
不可变类
- 例如String,Double
- 构建方法:
- 成员变量private final
- 构造器初始化成员变量,保证成员变量只在构造时赋值
- 只提供getter方法
- 不提供setter方法
抽象类
- 抽象类是一种特殊的父类,把不能实现的方法定义为抽象方法,让子类去实现
- 抽象类是一个模板
- 抽象类为继承而存在,避免子类设计的随意性
- 抽象类不能实例化
- abstract只能修饰类和普通方法,不能修饰变量、构造器、静态方法
- 满足以下三种情况的类必须是抽象类
- 含有抽象方法
- 继承了抽象类,但没有实现所有抽象方法
- 实现了一个接口,但没有实现所有方法
- 抽象类可以包含成员变量、构造器、普通方法、抽象方法、初始化块、内部类,其中的构造器只供继承使用,无法构造对象
接口
- 接口应当理解为规范,是各个类中抽象出来的规范
- 抽象类主要作为子类的公用模板,而接口主要规定了类之间的通信规范
- 面向接口编程是一种松耦合的设计模式
- 例如,主板上的插槽指定了一种规范,只要实现了该规范的硬件都能使用该插槽,至于该硬件是什么类型、什么厂商,主板无需关心
- 接口支持多继承,即一个接口可以继承多个接口,获得这些接口的常量和抽象方法
- 接口的元素
- 接口名称:可以使用形容词,如comparable、runable等
- 变量:只能是常量(pubic static final),且需要初始化
- 抽象实例方法:自动隐式添加public abstract,需要实现类去实现
- 类方法:直接使用接口来调用
- 默认方法:必须加default,实现类可以获得该方法,相当于继承
内部类
- 内部类与成员变量、构造器、方法一样,是外部类的组成部分
- 内部类可以使用public、default、protected、private四种修饰符
- 相对地,外部类只能使用public和default
- 内部类的好处:
- 内部类可以是private, 不允许其他类访问内部类,提供更好的封装
- 当一个类只与某一个类交互,就可以设计为这个类的private内部类
- 与外部类有更好的交互
-内部类可以访问外部类的所有变量和方法,包括私有的
-外部类只能访问内部类的非私有方法,不能访问内部类的成员变量和私有方法
枚举类
- 当一个类只能产生有限个实例时,使用枚举类
- enum枚举类是一种特殊的类,与class和interface关键字并列
- enum类默认继承java.lang.Enum类,而不继承Object类
- enum类不能显式继承其他类
- 构造示例
public enum Season {
//所有实例必须在第一行列出,实际上等同于new若干个本类的public final static变量
spring("春"), summer("夏"), autumn("秋"), winter("冬");
private String name;
//只能使用private构造器,即时不指定也默认是private
Season(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
- 枚举类可以实现接口,并在每个实例后实现各自的特殊方法
public enum Season implements Info{
spring("春"){
@Override
public void info() {
System.out.println("春暖花开");
}
}, summer("夏"){
@Override
public void info() {
System.out.println("生如夏花");
}
}, autumn("秋") {
@Override
public void info() {
System.out.println("风吹麦浪");
}
}, winter("冬") {
@Override
public void info() {
System.out.println("银装素裹");
}
};
}
- Enum类常用方法
- static classname[] values(),获取枚举类的所有实例
- int compareTo(实例名),根据定义顺序比较,返回1,0,-1
- String toString(),返回实例名称
- int ordinal(),根据类中定义的顺序,返回实例的索引号
网友评论