Day18 内部类、设计模式
- 面向对象
1.1内部类
1.1.1概述
- 内部类:类体中还有一个类的声明
- 当一个事务的内部,还有一个部分需要一个完整的结构进行描述
- 这个内部的完整结构一般只是为了让外部类使用,其他类都不使用
- 而内部类还有一个作用是 可以访问外部类中的私有化属性
1.1.2分类
- 分类:
-
成员变量:类体中没有static修饰的变量
-
成员变量-->成员内部类/普通内部类
-
静态变量-->静态内部类
-
局部变量-->局部内部类
-
形参/实参-->匿名内部类
1.1.3静态内部类
public class _02_OuterClass {
private static String s1 = “A”;
private String s2 = “B”;
/*
* 静态内部类,等同看作静态变量
* 可以使用权限控制修饰符
* 静态内部类中,可以声明所有属性,静态和成员都可以
* 静态内部类中,可以直接访问外部类的静态属性,不能直接访问成员属性
*
*/
static class InnerClass {
public static void m1() {
System.out.println(s1);
// System.out.println(s2);
//不能直接访问成员变量,但是有对象就可以
System.out.println(new _02_OuterClass().s2);
}
public static void m2() {//m2是成员方法
System.out.println(s1);
//虽然m2是成员变量,但是还是不能直接访问外部类的成员属性
//因为m2再InnerClass中,想要执行m2必须创建InnerClass对象
//但是创建他的对象时,不需要依赖于外部类对象
// System.out.println(s2);
}
}
public static void main(String[] args) {
//外部类.内部类
_02_OuterClass.InnerClass.m1();
//new 外部类.内部类()
InnerClass innerClass = new InnerClass();
innerClass.m2();
//当前类中 类名可以省略
InnerClass.m1();
innerClass = new InnerClass();
}
}
1.1.4成员内部类
public class _01_OuterClass {
private static String s1 = “A”;
private String s2 = “B”;
/**
* 成员内部类可以等同看作成员变量,类体中不需要使用static修饰
*
* 可以使用权限控制修饰符
*
* 成员内部类中 不能有 静态声明
* 成员内部类中 可以直接访问外部类的 所有属性
*
* 内部类的类名:外部类$内部类_01_OuterClass$InnerClass
*
* InnerClass是成员属性,等同于成员变量
*/
class InnerClass {
//不能有静态声明
// public static void m1() {
//
// }
public void m2() {
System.out.println(s1);
System.out.println(s2);
}
}
public static void main(String[] args) {
//1创建外部类对象
_01_OuterClass out = new _01_OuterClass();
//2创建内部类对象
InnerClass innerClass = out.new InnerClass();
//属性调用
innerClass.m2();
}
}
1.1.5局部内部类
- 局部内部类等用于局部变量,作用域在方法体中,执行完毕就弹栈
- 局部内部类 不能有静态声明
- 局部内部类 不能使用static修饰符
- 如果外部方法 是静态方法,则局部内部类不能直接访问外部类的属性
- 如果外部方法 是成员方法,则局部内部类中可以直接访问外部类的所有属性
- 局部内部类中如果要使用外部方法中的局部变量,则该变量必须使用final修饰(1.8开始,final可以省略)
public class _03_OuterClass {
private static String s1 = “A”;
private String s2 = “B”;
//静态方法
public static void m1() {
int i = 10;
// i = 2; 相当于有了final所以改不了
class InnerClass {
//不能有静态声明,只能有成员声明
// public static void m3() {}
public void m3() {
System.out.println(s1);
//因为外部方法是静态方法 所以不能直接访问外部类的成员属性
// System.out.println(s2);
//访问局部变量需要使用final,但是1.8开始可以省略
System.out.println(i);
}
}
//使用内部类
InnerClass innerClass = new InnerClass();
innerClass.m3();
}
//成员方法
public void m2() {
int i = 2;
class InnerClass {
// public static void m3() {}
public void m3() {
System.out.println(s1);
//因为外部方法是成员方法,所以可以直接使用外部类中的所有属性
System.out.println(s2);
System.out.println(i);
}
}
InnerClass innerClass = new InnerClass();
innerClass.m3();
}
public static void main(String[] args) {
m1();
_03_OuterClass out = new _03_OuterClass();
out.m2();
}
}
1.1.6匿名内部类
- 匿名内部类:在方法的调用的时候,需要传入一个类的对象,这个时候可以直接传入一个匿名内部类
- 一般该对象是接口的实现类对象,匿名内部类等于是子类,可以使用super等关键字
- 语法:方法(new 父类/接口(){类体})
- 匿名内部类,会自动创建一个对象传入
- 好处少定义一个类,缺点无法重复使用
public class _04_OuterClass {
public static void main(String[] args) {
//这个内部匿名类能充当接口的对象了
//接口本身是不能创建对象的
test(new UserLogin() {
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 test(UserLogin userLogin) {
//接口的的引用类型只有两种
// null 子类对象
userLogin.login("admin", "root");
}
}
interface UserLogin {
public void login(String username, String password);
}
1.2 设计模式
1.2.1概述
- 设计模式:就是在编码实践中,人们发现有很多的编码方式会经常用到
- 于是就总结出来,形成了固定的结构,这就是设计模式
1.2.2单例模式
1.2.2.1概述
- 单例模式:
-
实例化很多次,得到同一个对象,让某个类只能被实例化一次
- 实现步骤:
-
现在需要控制创建对象的数量,只有一个,所以就不能让用户决定创建或者不创建
-
1 不能让用户创建对象
-
创建对象需要调用构造方法,如果不让用户创建对象,也就意味着不能让用户访问构造方法
-
所以 构造方法 需要私有化
-
2 我们创建一个给他,并且只创建一次即可
-
上面已经把构造方法私有化了,就意味着用户创建不了对象了
-
那么这个时候,我们必须提供一个让用户能够获取对象的一个方法
-
既然是获取对象的方法,那么这个方法一定是静态方法
-
3 存储对象的变量
-
变量不存储,不能重复使用,所以为了保证对象只有一个,我们肯定是创建对象之后,进行重复使用
-
局部变量:具有临时性,方法执行完后就不存在了,下一次调用方法是时,变量初始化
-
成员变量:静态方法中不能操作成员变量
-
静态变量:和类相关,和类声明周期一致
-
所以应该创建一个用来保存当前类对象的静态变量
- 总结:
- 1构造方法私有化
- 2提供一个私有的静态的用来保存当前类对象的静态变量
- 3提供一个公共的静态方法,来获取该对象
- 根据创建对象的时机不同,分为两种
- 1 懒汉模式
-
用到的时候再创建对象,也就是第一次获取的时候
- 2 饿汉模式
-
类加载 的时候就立刻创建对象
1.2.2.2懒汉模式
//懒汉
public class Singleton_02 {
private Singleton_02() {
}
private static Singleton_02 s;
public static Singleton_02 getInstance() {
if (s == null) {
s = new Singleton_02();
}
return s;
}
1.2.2.3饿汉模式
public class Singleton_01 {
private static Singleton_01 singleton_01 = new Singleton_01();
private Singleton_01() {
//private不让用户调用
}
public static Singleton_01 getInstance() {
return singleton_01;
}
}
- 懒汉模式和饿汉模式的区别:
-
1内存角度
-
懒汉模式要好一些,用到的时候再创建,一般叫做懒加载/迟加载
-
饿汉模式浪费内存,还没用就创建了
-
2 线程安全角度
-
饿汉模式是再类加载阶段就初始化的,所以再多线程环境下没有问题,因为类只会加载一次
-
懒汉模式是再多线程并发性的情况下,就不行了,可能创建多个对象,但是可以通过双重校验枷锁解决
-
所以 一般我们使用懒汉模式居多,尽管在多线程下,也使用懒汉模式,使用双重校验枷锁解决并发问题即可
1.2.3工厂模式
1.2.3.1概述