1.1 Interface
1.1.1 是什么
Interface是定义接口关键字
语法 : public interface 接口名 { }
接口不能被实例化对象,接口中也没有构造方法
主要是解决java中单继承功能变弱的问题
一个类只能继承一个父类,但是可以实现很多接口,多个之间使用 逗号 隔开,由extends变成了implements
Java1.8之前 接口中只有抽象方法和常量,但是public,static,final,abstract 都可以省略
1.8开始 可以有静态,也可以有default(可以解决为普通类中的成员方法)
静态方法直接使用接口名调用即可
Default方法,实现类对象可以调用,也可以覆写
1.9开始 支持private 方法
1.1.2 怎么用
// 变量 就是常量, psf 可以省略
public static final int i = 2;
public int age = 2;
// 方法是抽象方法 ,public abstract可以省略
public abstract void m1();
public void m2();
void m3();
// 1.8 开始
// 静态方法,通过接口名.方法名() 调用
public static void test() {
System.out.println("静态方法");
}
// 默认方法,就等于类中的成员方法
// 必须通过实现类对象调用(因为接口不能实例化),也是可以被覆写的
public default void m4() {
System.out.println("默认方法");
}
1.1.3 注意
接口和接口之间是多继承
代码如下:
interface A {
default void m1() {
System.out.println(“默认方法”);
}
void m2();
}
interface B {
void m3();
}
interface C extends B, A {
void m4();
}
类和接口直接是多实现,代码如下:
class D implements A, B {
@Override
public void m3() {
}
@Override
public void m2() {
}
}
一个普通类实现一个接口,需要实现所有的抽象方法
一个抽象类实现一个接口,需要实现0~N个抽象方法
如果一个功能接口和抽象类都能完成,优先使用接口,因为这样会保留类的继承,意味着子类功能还可以增强
因为类是单继承,而和接口是多实现
1.2 类关系
1.2.1 继承
使用extends表示 又称为泛化关系
类A extends 类B
接口A extends 接口B,接口 C
类和类单继承
接口和接口多继承
1.2.2 实现
Implements
类A implements 接口B,接口C
类和接口是多实现
1.2.3 依赖
某个类中的局部变量,是另一个类对象引用,这种关系是临时性的,方法执行结束关系就不存在了,代码如下:
public static void main(String[] args) {
// 依赖关系
X x = new X();
m1(x);
m2(x);
}
// 依赖关系
public static void m1(X x) {
}
public static void m2(X x) {
}
public static void m3(){
X x = new X();
}
public static void m4(){
X x = new X();
}
}
class X {
}
1.2.4 关联
比依赖更强,一般是长期的
一个类中的成员变量是另一个类对象的引用,代码如下:
// 关联关系
X x = new X();
1.2.5 聚合
整体和局部可以分离,各自具有各自的生命周期
比如 : 一个公司由员工构成,就算公司倒闭,员工依然可以存活,因为员工也有员工的生命周期
比如A保存B的引用,这个引用一般是调用处传递过来的,这样的话A和调用处都保存B的引用,就算A被销毁了,B也不会被销毁,因为调用处还保存B的引用,代码如下:
public static void main(String[] args) {
// 依赖关系
X x = new X();
m1(x);
m2(x);
}
// 依赖关系
public static void m1(X x) {
}
public static void m2(X x) {
}
1.2.6 组合
组合关系要强与聚合关系,也有叫强聚合的
同样是整体和局部,只不过不可分离,局部没有独立的生命周期
比如 人和眼睛,大脑等,
比如A保存B的引用,这个引用一般是自己创建的(一般是构造方法或成员变量),这样没创建一个A对象,也会创建一个B对象,A对象销毁,B对象也会销毁成为垃圾数据,代码如下:
public static void m3(){
X x = new X();
}
public static void m4(){
X x = new X();
}
聚合和组合是关联的两种特例,是更强的关联
1.3 内部类
在一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内 部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使 用内部类
类体中还有一个类
内部类还有一个重要的作用,就是可以访问外部类的私有属性
静态变量 – 静态内部类
成员变量 – 普通内部类
局部变量 – 局部内部类
形参和实参 – 匿名内部类
1.3.1 成员/普通内部类
可以等同看做成员变量
成员内部类中不能有静态声明
成员内部类中可以直接访问外部类所有属性
可以使用访问权限控制修饰符
内部类类名 : 外部类$内部类
代码如下:
// 私有静态
private static String s1 = “A”;
// 私有成员
private String s2 = “B”;
// 类体中 没有static修饰的类是成员内部类
class InnerClass {
// 成员内部类中不能有静态声明
// static int i = 2;
// public static void m1(){}
public void m2() {
System.out.println(s1);
System.out.println(s2);
}
}
public static void main(String[] args) {
// 创建成员内部类对象
_01_OuterClass oc = new _01_OuterClass();
InnerClass ic = oc.new InnerClass();
ic.m2();
}
1.3.2 静态内部类
静态内部类可以看做静态变量
静态内部类中可以有任何声明
静态内部类中可以直接访问外部类静态数据,无法直接访问成员数据
代码如下:
// 私有静态
private static String s1 = “A”;
// 私有成员
private String s2 = “B”;
// 类体中使用static修饰的类是静态内部类
static class InnerClass {
public static void m1() {
System.out.println(s1);
// System.out.println(s2);
}
public void m2() {
System.out.println(s1);
// System.out.println(s2);
// 有对象就行
System.out.println(new _02_OuterClass().s2);
}
}
public static void main(String[] args) {
_02_OuterClass.InnerClass.m1();
InnerClass ic = new _02_OuterClass.InnerClass();
ic.m2();
// 访问当前类的静态属性,类名可以省略
InnerClass.m1();
InnerClass ic1 = new InnerClass();
ic1.m2();
}
1.3.3 局部内部类
局部内部类就等同于局部变量
局部内部类访问外部方法的局部变量的时候,该变量需要加final修饰,1.8开始final可以省略
不管外部方法是静态还是成员,局部内部类中都不能使用static修饰类,同时类中也不能有静态声明
如果外部方法是成员方法,则局部内部类中可以直接访问外部类任何属性
如果外部方法是静态方法,则局部内部类中不能直接访问外部类的成员属性
局部内部类名字是 : 外部类$1内部类 , 外部类$2内部类 以此类推
代码如下:
// 私有静态
private static String s1 = “A”;
// 私有成员
private String s2 = “B”;
public static void m1() {
int age = 2;
class InnerClass {
// 局部内部类不能有静态声明
// public static void m3(){}
public void m4() {
// age 应该加final修饰,但是1.8开始 final可以省略,但是age的值不能更改
System.out.println(age);
System.out.println(s1);
// 因为是静态方法中的局部内部类所以不能直接访问外部类的成员属性
// System.out.println(s2);
}
}
// 局部内部类调用,只能在该方法体内部
InnerClass ic = new InnerClass();
ic.m4();
}
public void m2() {
int age = 2;
class InnerClass {
// 局部内部类不能有静态声明
// public static void m3(){}
public void m4() {
// age 应该加final修饰,但是1.8开始 final可以省略,但是age的值不能更改
System.out.println(age);
System.out.println(s1);
// 因为是成员方法中的局部内部类所以能直接访问外部类的成员属性
System.out.println(s2);
}
}
// 局部内部类调用,只能在该方法体内部
InnerClass ic = new InnerClass();
ic.m4();
}
public static void main(String[] args) {
m1();
_03_OuterClass oc = new _03_OuterClass();
oc.m2();
}
1.3.4 匿名内部类
匿名内部类 : 指在调用方法时,需要传入一个对象(一般是接口的实现类对象),此时可以不传递实现类对象,传递一个匿名内部类
普通类也可以,匿名内部类就等于是普通类的子类
创建内部类的时候,系统会自动帮我们创建一个内部类对象,并且只创建一次
优点 : 少定义一个类
缺点 : 无法重复使用
不能有静态声明,但是可以声明常量
静态变量和静态方法不能声明
不能直接访问外部类的成员属性
类名 : 外部类$1 , 外部类$2 以此类推
一般应用于 : 方法调用时,传递参数, 方法参数一般是一个接口,代码如下:
public static void main(String[] args) {
login(new ILoginService() {
static final int age = 2;
@Override
public void login(String username, String password) {
if (username.equals("admin")) {
if (password.equals("root")) {
System.out.println("登陆成功");
} else {
System.out.println("密码不正确");
}
} else {
System.out.println("用户名不存在");
}
}
});
}
public static void login(ILoginService loginService) {
loginService.login("admi1n", "root1");
}
}
interface ILoginService {
/
用户登陆,并作出合理提示
@param username
用户名为admin
@param password
密码为root
/
public void login(String username, String password);
}
1.4 设计模式
1.4.1 概述
就是在编码实践中,程序员发现有很多编码方式经常被用到,于是总结出来形成固定写法,一般表示最佳实践,就是设计模式
1.4.2 单例模式
1.4.2.1 概述
就是让某个类只能被实例化一次,一般这个实例化对象由这个类去创建,然后提供一个公共的获取唯一对象的一个接口
根据对象创建时机不同,被分为两种方式
1 懒汉模式
2 饿汉模式
1.4.2.2 实现步骤
就是让某个类只能被实例化一次,一般这个实例化对象由这个类去创建,然后提供一个公共的获取唯一对象的一个接口 根据对象创建时机不同,被分为两种方式
1 懒汉模式
2 饿汉模式
实现步骤 :
既然要控制创建对象的数量,就不能让用户去决定是否创建对象
而创建对象的语句是 new 构造方法() ; , 通过构造方法创建对象,而我们不让用户创建对象
所以 应该不让用户访问构造方法,应该把构造方法私有化,这样创建对象的决定权就在当前类中
1 构造方法私有化
上面步骤,已经把构造方法私有化了,就意味着用户创建不了对象了
那么这个时候,我们还需要想办法把该对象返回给用户,也就是必须提供一个专门获取这个对象的方法
这个方法,一定是公共的静态方法
2 创建一个公共的静态方法,用户获取当前类的对象,并且保证只创建一次
获取对象的方法有了,下面就是要保证对象的唯一性了,想要重复使用(唯一) 必须先存储
存储方式 : 需要创建一个当前类类型的变量
局部 变量 : 不行,因为每次调用该方法的时候,该变量都会重新初始化赋值
静态 变量 : 没问题,因为静态在整个程序生命周期中只初始化一次
成员 变量 : 不行,因为静态上下文中无法引用非静态属性
3 创建一个私有化静态变量,用来存储当前类的对象
下面程序 : 类加载阶段创建对象 叫饿汉模式
1.4.2.3 饿汉模式
下面程序 : 类加载阶段创建对象 叫饿汉模式:
private static SingLeton_01 obj = new SingLeton_01();
private SingLeton_01(){
}
public static SingLeton_01 getInstance(){
return obj;
}
1.4.2.4 懒汉模式
懒汉模式 : 第一次使用的时候,再创建对象
private static SingLeton_02 obj = null;
private SingLeton_02() {
}
public static SingLeton_02 getInstance() {
if (obj == null) {
obj = new SingLeton_02();
}
return obj;
}
1.5 工厂模式
把创建对象语句,封装到工厂类中,提供一个获取对象的方法即可
这样所有用到这个对象的地方,都去工厂中获取,把类之间的强依赖关系变弱,灵活度更高
定义一个用于创建产品的接口,由子类决定生产什么产品。
是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象