2022-07-27 java之静态、单例、内部类
目录
一 、static关键字
1.1 概念
static 关键字 可以修饰成员变量和成员方法 ,一旦成员修饰之后,成员不属于对象层次,而属
于类层级,也就是用创建对象来调用就不可行。
1.2 (静态)类变量
用static来修饰的成员变量,叫类变量,该类每个对象共享这个类变量值,每个对象都可以修改
类变量的值,甚至可以在不创建对象情况下对类变量来操作。
public class Student {
//成员变量
String name;
String sex;
static String classId;
public static void main(String[] args) {
//静态成员变量,操作共享空间
Student.classId = "001";
//普通成员变量,只能操作自己空间内属性
Student s1 = new Student();
s1.name = "tom";
s1.sex = "male";
Student s2 = new Student();
s2.name = "Jerry";
s2.sex = "female";
System.out.println(s1.name + "/" + s1.sex + "/" + Student.classId);
System.out.println(s2.name + "/" + s2.sex + "/" + Student.classId);
System.out.println(s2.name + "/" + s2.sex + "/" + Student.classId);
}
}
1.2.1 静态成员变量和成员变量区别
- 所属不同:
静态成员变量属于类,所以叫类变量
成员变量属于对象,所以叫实例变量 - 内存中位置不一样
静态变量存储于方法区静态区
成员变量存储于堆内存中 - 内存中出现的时间不一样
静态变量随着类加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失 - 调用不同
静态变量可以通过类名调用(斜体)
成员变量只能通过对象名(引用)来调用。
1.3 静态方法
用static 关键字修饰的成员方法,叫静态方法
- 静态方法只能访问静态方法,不能访问非静态方法。
- 静态方法可以访问类变量,不能访问非静态变量 【静态只能访问静态】
- 普通成员可以静态成员
//静态方法
public static void study(){
System.out.println("学生必须好好学习");
// playGame();
classId="001";
// name="xxx";
}
//普通方法
public void playGame(){
classId="001";
System.out.println("有时也可以玩玩游戏");
study();
}
1.4 静态代码块
语法格式
static{
//静态代码块
}
二、 设计模式 单例模式
2.1 概念
- 设计模式(Design Pattern)是一套反复使用的,经过分类的,代码设计经验的总结
- 设计模式是软件开发人员在软件开发过程中面对一般性问题解决方案
- 项目中合理运用设计模式可以解决很多问题
软件设计模式的分类(面向对象领域) 23种设计模式,总共分3大类
- 创建型模式
- 结构型模式
- 行为型模式
掌握 单例模式 工厂模式 代理模式
2.2 单例模式(singleton)
- 一个实例
- 一个朝代,皇帝只有一个
- 一山不能容二虎
- 计算机系统
- 回收站
- 网络共享打印机
目标: 使类中一个对象成为该系统唯一实例
定义: 一个类有且只有一个实例,并且自行实例化,并向整个系统提供
特点:
- 某个类只有一个对象
- 必须自行实例化
- 必须自行向整个系统 提供个实例实现
- 提供私有构造方法
- 有一个静态私有的对象作为成员变量
- 提供一个公有静态方法用于创建,获取静态私有对象分类
饿汉式:
//饿汉式
public class Singleton1 {
private static Singleton1 instance = new Singleton1();
public void show() {
System.out.println("冲就完了!");
}
private Singleton1() {
}
public static Singleton1 getInstance() {
return instance;
}
}
懒汉式:
//懒汉式
public class Singleton {
private static Singleton instance;
private Singleton (){}
public void show(){
System.out.println("冲就完了!");
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2.3 饿汉式和懒汉式的区别
- 创建时机
饿汉式 :类加载时,创建实例
懒汉式:方法调用时,创建实例 - 线程安全
饿汉式线程安全
懒汉式线程不安全
三、内部类
1.什么是内部类
将一个类A定义在另一个类B里面,里面那个类A称为内部类,B则称为外部类。
class B{
*** Class A;
//成员变量 ->成员内部类(1)
public void method(){
Class A;//-》方法内部类(2)
}
pubic static method(){
Class A//-》静态内部类(3)
}
}
2. 成员内部类
- 成员内部类:定义中类中,方法外的类
class 外部类{
class 内部类{
}
}
在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类的结构;比如:汽车类Car
中包含发动机类Engine,这是Engine就可以使用内部类来描述,定义在成员位置
//外部类
class Car{
//内部类
class Engine{
}
}
3.访问特点
- 内部类可以直接访问外部类的成员,包括私有成员。
- 外部类要访问内部类成员,必须要建立内部类对象
- 创建内部类对象格式
- 外部类.内部类名 对象名=new 外部类型().new 内部类型();
4. 实例
package demo01;
public class Person {
private boolean live=true;
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
class Heart{
public void jump(){
//直接访问外部类
if(live){
System.out.println("心脏在跳动!");
}else{
System.out.println("心脏不跳了!");
}
}
}
}
----------------------------------------------------------
package demo01;
public class InnerDemo {
public static void main(String[] args) {
//创建外部类的对象
Person p=new Person();
Person.Heart heart=p.new Heart();
// Person.Heart heart1=new Person().new Heart();
//调用内部类的方法
heart.jump();
//调用外部类
p.setLive(false);
heart.jump();
}
}
输出结果:
心脏在跳动!
心脏不跳了!
内部类仍然是一个独立的类,在编译之后 内部类会编译成独立的.class文件,但是前面冠以
外部类类名和符号$
Person$Heart.class
- 匿名内部类 【重点】
匿名内部类:是内部类的简化写法,它的本质是一个父类或者父接口的匿名子类对象。
开发中,最常用内部类就是匿名内部类,并且Lambda表达式是对匿名内部类的简化。
使用场景
当使用接口,先定义一个接口,接下来
- 定义接口实现类(子类)
- 在子类中重写接口抽象方法
- 创建实现类对象
- 调用重写的后方法
我们的目的,最终是为了调用方法,那么能不能简化一下,把四步合成一步呢?匿名内部类就是
这样的作快捷方式
前提 匿名内部类必须继承一个父类或实现一个父接口-》需要方法重写
格式:
new 父类名或接口名(){
//方法重写
@Override
pubilc void methd(){
//执行语句
}
};
使用:
以接口为例
public interface FlyAble {
public abstract void fly();
}
创建了匿名的内部类,并调用:
public class Test {
public static void main(String[] args) {
/* FlyAble f=new FlyAbleImpl();
f.fly();*/
FlyAble f=new FlyAble() {
@Override
public void fly() {
System.out.println("我能飞");
}
};
//调用,执行重写的方法
f.fly();
}
}
通常以方法形参方式,使用匿名内部类
public class Test01 {
//将接口作为形参定义在方法中
public static void showFly(FlyAble f){
f.fly();
}
public static void main(String[] args) {
FlyAble f=new FlyAble() {
@Override
public void fly() {
System.out.println("我能飞");
}
};
//将引用作为实参传递到方法中
showFly(f);
}
}
以上两步,也可以简化成一步,代码如下:
public class Test03 {
public static void showFly(FlyAble f){
f.fly();
}
public static void main(String[] args) {
showFly(new FlyAble() {
// public static int 2;
// public abstract void method()
@Override
public void fly() {
System.out.println("我能飞");
}
});
}
}
注意事项:
- 匿名内部类不能定义静态成员。
- 匿名内部类不能再抽象方法