eclipse快捷键
- syso alt+/
- main alt+/
- 运行:Ctrl+F11
- 多行注释:Ctrl+Shift+/
- 多行编辑:Alt+Shift+A
- 大小写:Ctrl+Shift+X (小变大) Ctrl+Shift+Y(大变小)
- 快速创建getter与setter:点击Source→点击Generate Getters and Setters
- 创建无参构造器:source→generate constructors form Superclass→点击generated
- 快速创建有参构造器:source→generate constructor using fields
- 快速重写toString方法:toString的类→Source→Generate toString()
- 查看类的继承关系:选中想要查看的类,Ctrl+T
浮点数运算会产生误差
浮点数0.1
在计算机中就无法精确表示,因为十进制的0.1
换算成二进制是一个无限循环小数,很显然,无论使用float
还是double
,都只能存储一个0.1
的近似值。但是,0.5
这个浮点数又可以精确地表示。
因为浮点数常常无法精确表示,因此,浮点数运算会产生误差,例:
public class floatoperation {
public static void main(String[] args) {
double x = 1.0 / 10 ;
double y = 1 - 9.0/10;
double a = 0.1 ;
double b = 1 / 10 ;
if(a == b) {
System.out.println("相等");
}else {
System.out.println("卧槽!");
}
}
}
代码输出:卧槽!
如果参与运算的两个数其中一个是整型,那么整型可以自动提升到浮点型
如果参与运算的两个数其中一个是整型,那么整型可以自动提升到浮点型
int n = 5;
double d = 1.2 + 24.0 / n;
// 6.0
在一个复杂的四则运算中,两个整数的运算不会出现自动提升的情况。例如
double d = 1.2 + 24 / 5; // 5.2
计算结果为5.2
,原因是编译器计算24 / 5
这个子表达式时,按两个整数进行运算,结果仍为整数4
。
四舍五入
如果要进行四舍五入,可以对浮点数加上0.5再强制转型:
double d = 2.6;
int n = (int) (d + 0.5);
布尔运算
对于布尔类型boolean
,永远只有true
和false
两个值。
短路运算
如果一个布尔运算的表达式能提前确定结果,则后续的计算不再执行,直接返回结果。因为false && x
的结果总是false
,无论x
是true
还是false
,因此,与运算在确定第一个值为false
后,不再继续计算,而是直接返回false
。
类似的,对于||
运算,只要能确定第一个值为true
,后续计算也不再进行,而是直接返回true
。
char
字符类型String
字符串类型- """ ··· """多行字符串
输出数组元素
public static void main(String[] args) {
int [] ary; //新建数组
ary = new int[] {1,2,3,4,5}; //新建数组
String[] a =new String [5]; //麻烦新建数组
int[] ns = { 68, 79, 91, 85, 62 }; //最简单新建数组
a[0] = "-";
a[1] = "--";
a[2] = "---";
a[3] = "----";
a[4] = "-----";
for (String x : a) {
System.out.println(x);
}
}
数组反转
八种基本数据类型
- int
- float
- Char
- boolean
- long
- double
- byte
- short
一个源文件中最多只能有一个public类,其它类的个数不限
如果源文件中包含一个public类,则文件名必须按该类名命名
java代码规范
- 类、方法的注释要以javadoc的方式来写
- 非javadoc的注释是给代码的维护者看的
String类型转基本数据类型
通过基本类型的包装类调用parseXX方法
String x = "123";
int num = Integer.parseInt(x);
float num2 = Float.parseFloat(x);
double num3 = Double.parseDouble(x);
System.out.println(num);
System.out.println(num2);
System.out.println(num3);
输入
需要导包import java.util.Scanner;
Scanner myscanner= new Scanner (System.in);
System.out.println("请输入大小");
String name = myscanner.next();
System.out.println("不要说谎哦,请重新输入");
String newname = myscanner.next();
类于对象的内存
- 栈:一般存放基本数据类型(局部变量)
- 堆:存放对象(Cat cat ,数组等)
- 方法区:常量池(常量,如字符串),类加载信息
创建对象的流程简单分析(韩顺平199)
Person p = new Person();
p.name = "jack";
p.age = 10;
- 先加载Person类信息(属性和方法信息,只会加载一次)
- 在堆中分配空间,进行默认初始化,
- 把地址赋给p,p就指向对象
- 进行指定初始化
调用方法必须先创建对象
方法调用小结
- 当程序执行到方法时就会开辟一个独立的空间(栈空间)
- 当方法执行完毕,或者执行到return语句时就会返回
- 返回到调用方法的位置
- 返回后继续执行后面的代码
使用方法的优点
- 提高代码复用性
- 可以将实现的细节封装起来,然后供其他用户来调用即可
成员方法的定义
访问修饰符 返回数据类型 方法名 (形参列表){//方法体
语句;
return 返回值;
}
成员方法注意事项和使用细节
- 访问修饰符(左右时控制方法使用的范围)
- 如果不写则为默认访问【有四种:public、protected、private和默认】
- 返回数据类型
- 一个方法最多有一个返回值【如果返回多个可以考虑使用数组】
- 返回类型可以为任意类型
- 形参列表
- 一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开
- 参数类型可以为任意类型
- 调用到参数的方法时,要对应参数列表传入相同类型或兼容类型的参数
- 形参与实参类型要一致或兼容、个数顺序必须一致
- 方法体
- 方法不能嵌套定义
- 方法调用细节说明
- 同一个类中的方法直接调用
- 跨类中的方法A类调用B类方法:需要通过对象名调用。比如 对象名.方法名(参数)
方法重载
-
基本介绍
- java中允许同一个类中多个同名方法的存在 ,但要求形参列表不一致
-
重载的好处
- 减轻了起名的麻烦
- 减轻了记名的麻烦
可变参数
-
基本概念:java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。就可以通过可变参数实现。
-
基本语法:
访问修饰符 返回类型 方法名 (数据类型... 形参名){
}
-
例:
//可变参数可以优化方法重载
//int...表示接受的是可变参数,类型是int,即可以接收多个int(0-多)
//使用可变参数时,可以当作数组来使用 即nums可以当作数组
//遍历nums求和即可
public int sum (int... nums){
int res = 0;
for(int i = 0; i < nums.length; i++){
res += nums[i];
}
return res;
}
可变参数的注意事项和使用细节
- 可变参数的实参可以为0个或任意多个
- 可变参数的实参可以为数组
- 可变参数的本质就是数组
- 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
- 一个形参列表只能有一个可变参数
作用域
-
在java编程中,主要的变量就是属性(成员变量)和局部变量
-
我们说的局部变量一般是指在成员方法中定义的变量
-
java中作用域的分类
- 全局变量:也就是属性,作用域是整个类体
- 局部变量:也就是除了属性之外的其他变量,作用域为定义他的代码块中
-
全局变量可以不用赋值,直接使用,因为有默认值,局部变量必须赋值后才能使用,因为没有默认值
作用域的注意事项和使用细节
-
属性和局部变量可以重名,访问时遵循就近原则
-
在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名
-
属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。局部变量生命周期较短,伴随着代码块的执行而创建,伴随着代码块的结束而销毁,即在一次方法的调用过程中
-
作用域范围不同
- 全局变量/属性:可以呗被本类使用,或其他类使用(通过对象调用)
- 局部变量:只能在本类中对应的方法中使用
-
修饰符不同
-
全局变量/属性可以加修饰符
例:
public int age = 20;
-
局部变量不可加修饰符
-
构造方法/构造器
-
基本介绍
构造方法又叫构造器,是类的一种特殊的方法,他的主要作用是完成对新对象的初始化。他有几个特点:
- 方法名和类名相同
- 没有返回值
- 在创建对象时,系统会自动的调用改类的构造器完成对对象的初始化
-
基本句法
[修饰符] 方法名 (形参列表){
方法体;
}
- 构造器的修饰符可以默认,也可以是
public
protected
private
- 构造器没有返回值
- 方法名和类名必须一致
- 参数列表和成员方法一样的规则
- 构造器的调用系统完成
- 构造器的修饰符可以默认,也可以是
构造器注意事项和使用细节
- 一个类可以定义多个不同的构造器,即构造器重载
- 构造器名和类名要相同
- 构造器没有返回值
- 构造器时完成对象的初始化,并不是创建对象
- 在创建对象时,系统自动的调用该类的构造方法
- 如果没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造方法)
- 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显示的定义一下
为什么要用this关键字
当使用构造器时,新建的带参数的构造器传入的形参名和类的属性里的名字相同时,由于受到作用域的影响,并不能将实参传入,所以引出this
例:
public class Account {//注意使用的时候类名问题,类名要和文件同名
String name;
//有参构造器
public Account(String name) {
name = name;
}
public void showInfo() {
System.out.println("name="+name);
}
public static void main(String[] args) {
Account account = new Account("阿黄");
account.showInfo();
}
这段代码运行是得不到想要的结果的
解决方案:
- 构造器name前加
this.
- 构造器形参名用除name之外命名
最好用第一种,不要用第二种
this关键字
java会给每个对象分配this
,代表当前对象;简单来说那个对象调用,this
就代表那个对象
this的注意事项和使用细节
- this关键字可以用来访问本类的属性、方法和构造器
- this可以区分当前类的属性和局部变量
- 访问成员方法的语法:
this
.方法名(参数列表) - 访问构造器语法:
this
(参数列表);注意只能在构造器中使用 this
不能在类定义的外部使用,只能在类定义的方法中使用
抽象类
- 在面向对象的概念中,所有的对象都是通过类来描绘的,但是并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对,这样的类就是抽象类
- 抽象类不能实例化对象
- 由于抽象类不能实例化对象,所以抽象类必须被继承才能被使用
- 抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类可以实现多个接口
接口
- 通常以
interface
,类通过继承接口的方式来继承接口的抽象方法 - 接口并不是类,但是编写接口的方式和类相似,他们是不同的概念。类是描述对象的属性和方法;接口则要包含类要实现的方法
- 除非实现接口的类是抽象类,否则改类要定义接口的所有方法
- 接口无法被实例化,但可以被实现
接口与类的相似点
- 一个接口可以有多个方法
- 接口文件保存在.java文件中,文件名使用接口名
- 接口的字节码文件保存在 .class 结尾的文件中。
- 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口与类的区别
- 接口不能用于实例化对象
- 接口没有构造方法
- 接口中所有方法必须是抽象方法
- 接口不能包含成员变量,除了static和final变量
- 接口不是被类继承了,而是要被类实现
- 接口支持多继承
接口与抽象类的区别
- 抽象类中的方法可以有方法体,就是实现方法的具体功能,但是接口中的方法不行
- 抽象类中的变量可以是各种类型的,而接口中的成员变量只能是public、static、final类型的
- 接口中不能含有静态代码块以及静态方法(用static修饰的方法),而抽象类可以有静态代码块和静态方法
- 一个类只能继承一个抽象类,而一个类可以实现多个接口
包
包的三大作用
- 区分相同名字的类
- 当类很多时,可以很好的管理类
- 控制访问范围
包的基本语法
package 包名;
说明:package 关键字,表示打包
包的本质
时间上就是创建不同的文件夹来保存文件
包的注意事项和细节
- package的作用是声明当前类所在的包,需要放在类的最上边,一个类最多只有一句package
- import放在package后面
访问修饰符
java提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围)
- 公开:public,对外公开
- 受保护:protected,对子类和同一个包中的类公开
- 默认:没有修饰符号,向同一个包的类公开
- 私有:private,只有类本身可以访问,不对外公开
访问级别 | 访问控制修饰符 | 同类 | 同包 | 子类 | 不同包 |
---|---|---|---|---|---|
公开 | public | √ | √ | √ | √ |
受保护 | protectde | √ | √ | √ | × |
默认 | 没有修饰符 | √ | √ | × | × |
私有 | private | √ | × | × | × |
使用的注意事项
- 修饰符可以用来修饰类中的属性,成员方法以及类
- 只有默认的和public才能修饰类,并且遵循上述访问权规则
封装(个人理解)
public class T{
private String name;
private int age;
public String getname(){
return name;
}
public int getage(){
return age;
}
public void setname (String name){
this.name = name;
}
public void setage (int age){
this.age = age;
}
}
- 类中定义私有属性,私有属性不可被外部访问,因此要想使用必须定义get和set方法,
- getname()、getage()方法是外部类访问该类成员变量的入口
- 通过setname()、setage()可以设置其中的值
继承
继承可以解决代码复用,只需要通过extends来声明继承父类即可
- 继承的基本语法
class 子类 extends 父类{
}
子类就会继承父类定义的属性和方法
继承使用细节(代码MXDX01.jicheng01.Test)
- 子类继承了所有的属性和方法,但是私有的属性和方法不能在子类直接访问,要通过公共的方法去访问
- 子类必须调用父类的构造器,完成父类的初始化(默认在子类构造器中存在一个super()函数)
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器,完成父类的初始化,否则编译不会通过。
- 如果需要指定去调用父类的某个构造器,则显示的调用一下:super(参数列表)
- super在使用时,需要在构造器第一行,super只能在构造器中使用
- super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
- java所有类都是Object的子类,object类是所有类的基类
- 构造器的调用不限于直接父类,将一直往上追溯到Object类(即构造器的调用时先会一级一级往上找,找到最顶层的父类,从最顶层的父类开始执行)
- 子类最多只能继承一个父类(指直接继承)即java中是单继承机制
思考:如何让A类同时继承B、C类
可以先让B类继承C类,然后A类继承B类 - 不能滥用继承,子类和父类之间必须满足is-a 的逻辑关系 例:
Person is a Music? Person 不是 Music,不满足is-a的关系,不合理
Dog extents Animal 合理
this存在的意义
public class GZtest {
/**
* this()调用构造函数存在的意义
* */
String name;
int age;
public GZtest() {//无参构造器
System.out.println("我是无参构造");
System.out.println("=======================");
}
public GZtest(String name) {//一参构造器
this(); //调用无参构造器
this.name = name;
System.out.println("我是一参构造");
System.out.println("=======================");
}
public GZtest(String name,int age) {//二参构造器
this(name); //调用无参构造器
this.age = age;
System.out.println("我是二参构造");
System.out.println("=======================");
public void showinfo() {
System.out.println("名字是:"+name+",年龄为:"+age);
}
public static void main(String[] args) {
GZtest gztest = new GZtest("小明",12);
gztest.showinfo();
}
}
- 个人认为this()调用构造函数的意义就是让代码变得更加简洁
- 对this调用必须是构造方法中的第一个语句,否则便会出错,当然也不能在普通方法中调用构造方法
继承的本质分析
public class ExtendsTheory {
public static void main(String[] args) {
Son son = new Son();//内存的布局
System.out.println(son.name);
System.out.println(son.age);
System.out.println(son.hobby);
//返回的是什么
//1、首先看子类是否有该属性
//2、如果子类有这个属性,并且可访问,则返回信息
//3、如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息)
//4、如果父类没有就按照3的规则,继续找上级父类,直到Object
//5、如果都没有就会报错
}
}
class Grandpa{//爷类
String name = "大头爷爷";
String hobby = "烫头";
}
class Father extends Grandpa{//父类
String name = "大头爸爸";
int age = 46;
}
class Son extends Father{//好大儿类
String name = "大头儿子";
}
super关键字
代表父类的引用,用于访问父类的属性、方法、构造器
- 访问父类的属性,但不能访问父类的private属性
- 访问父类的方法,但不能访问父类的private方法
- 访问父类的构造器
super(参数列表),只能放在构造器的第一句
super和this的比较
区别 | this | super |
---|---|---|
访问属性 | 访问本类中的属性,如果本类没有此属性则从父类中继续查找 | 从父类开始查找属性 |
调用方法 | 访问本类中的方法,如果本类没有此方法则从父类继续查找 | 从父类开始查找方法 |
调用构造器 | 调用本类构造器,必须放在构造器的首行 | 调用父类构造器,必须放在子类构造器的首行 |
特殊 | 表示当前对象 | 子类中访问父类对象 |
方法重写
简单地说,方法重写,就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样那么就说子类的这个方法重写了父类的方法。
需要满足以下条件
- 子类方法的参数方法名,要和父类方法的参数,方法名称完全一样
- 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
- 子类方法不能缩小父类方法的访问权限
多态
方法或对象有多种形态,是面向对象的第三大特征,多态是建立在封装和继承的基础之上多的
方法的多态
- 方法的多态,重写和重载体现多态
对象的多态(核心、重点)案例见:MXDX01.duotai.poly.polyobjct
- 一个对象的编译类型和运行类型可以不一致,例:
Animal animal = new Dog();
animal的编译类型是Animal,运行类型是Dog
Animal animal = new Cat();
animal的运行类型是Cat,编译类型仍然是Animal - 编译类型在定义对象时就确定了,不能改变
- 运行类型是可以变化的
- 编译类型看定义时 = 号的左边,运行类型看 = 的右边
多态注意事项和细节
多态的前提是两个类存在继承关系
多态的向上转型
- 本质:父类的引用指向了子类的对象
- 语法:父类类型 引用名 = new 子类类型;
- 特点:编译类型看左边;,运行类型看右边可以调用父类中的所有成员(须遵守访问权限),不能调用子类中特有成员
- 最终运行效果看子类的具体实现
向上转型调用方法规则
- 可以调用父类中的所有成员(需遵守访问权限)
- 但是不能调用子类的特有成员;因为在编译阶段能调用那些成员是由编译类型来决定的
- 最终运行效果看子类(运行类型)的具体实现,即调用方法时,按照从子类(运行类型)开始查找方法,然后调用规则:
1、先找本类如果有就调用
2、没有就找父类
3、父类没有就找父类的父类。如果没找到或者找到不能访问就报错
多态的向下转型
- 语法:子类类型 引用名 = (子类类型)父类引用
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,可以调用子类类型中的所有成员
属性重写问题
属性没有重写之说
instanceOf 比较操作符,用于判断对象的运行类型是否为XX类型或者XX类型的子类型
例:aa instanceof BB 即,判断aa是不是BB类型,或者aa是BB类型的子类
动态绑定机制
- 当第调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明哪里使用
多态数组
详见MXDX01.duotai.polyarr_
多态参数
方法定义的形参类型为父类类型,实参类型允许为子类类型
java理解
各自放在各自的类里,统一调用
例:经理和普通工人工资组成不同
员工类{姓名,工资}
经理类{姓名,工资,工作}//重写工资方法
普通工人{姓名,工资,工作}
虽然员工和经理类型不同,但是展示类通过同一个方法调用打印出工资,通过多态继承,员工和经理分别调用自己的方法打印出工资
== 和equals 比较
- ==
- == 是比较运算符
- == 既可以判断基本类型,又可以判断引用类型
- 如果判断基本类型,判断的是值是否相等
- 如果判断的是引用类型,判断的是地址是否相等,即判断是不是同一个对象
- equals方法
- equals是Object中的方法,只能判断引用类型
- 默认判断地址是否相等,子类中往往重写该方法,用于判断内容是否相等
hashCode方法
- 提高具有哈希结构的容器的效率
- 如果两个引用指向同一个对象,则哈希值一样
- 如果两个引用指向的是不同的对象,则哈希值是不一样的
- 哈希值主要是根据地址来计算的,但不能完全将哈希值等价于地址
toString方法
默认返回:全类名+@+哈希值的十六进制
重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString形式
当直接输出一个对象时,toString方法会被默认调用
finallize方法
- 当对象被回收时,系统自动调用该对象的finallize方法。子类可以重写该方法,做一些释放资源的操作
- 什么时候被回收:当某个对象没有被任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法
类变量和类方法
定义:
访问修饰符 static 数据类型 变量名;(推荐)
static 访问修饰符 数据类型 变量名
如何访问:
类名.类变量名
类变量使用注意事项
- 什么时候需要类变量 当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量)
- 类变量与实例变量(普通属性)区别 类对象是该类的所有对象共享的,而实例对象是每个对象独享的
- 加上static称为类变量或静态变量,否则称为实例变量、普通变量、非静态变量
- 类变量可以通过类名.类变量名 或者对象名.类变量名来访问
- 实例变量不能通过 类名.类变量名方式访问
- 类变量是在类加载时就初始化了,也就是说,即使没有创建对象,只要类加载了,就可以使用类变量了
- 类变量的声明周期是随着类的加载开始,随着类消亡而销毁
类方法的使用场景
- 当方法中不涉及到任何对象相关的成员,则可以将方法设计成静态方法,提高开发效率
- 开发自己的工具类时可以将方法做成静态,方便调用
类方法中使用注意事项
- 静态方法可以访问本类的静态成员
- 静态main方法不可以访问本类的非静态成员
- 静态main方法要访问本类的非静态成员,需要先创建对象,再调用即可
- 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区;类方法中不能用this参数;普通方法可以用this参数
- 类方法可以通过类名调用,也可以通过对象名调用
- 普通方法和对象有关,需要通过对象名调用
- 类方法中不允许使用和对象有关的关键字,比如this和super普通方法(成员变量)可以
- 类方法(静态方法)中只能访问静态变量或静态方法
- 普通成员方法,既可以访问非静态成员,也可以访问静态成员
理解main方法语法
public static viod main(String[] args){}
- main方法是虚拟机调用
- java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public
- java虚拟机在执行main()方法时不必创建对象,所以该方法必须时static
- 该方法接收String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数,
eclipse动态传值
代码块
属于类中的成员,类似于方法,将逻辑语句封装在方法体中通过{}包围起来
但和方法不同,没有方法名,没有返回值,没有参数,只有方法体,而且不用通过方法或类现实的调用,而是加载类时或者创建对象时隐式调用
基本语法
[修饰符]{
代码
};
注意:
- 修饰符可选,要写的话只能写static
- 代码块分为两类,使用static修饰符的叫静态代码块,没有static的叫普通代码块
- 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、判断、循环等)
- ;号可以省略也可以不写
代码块细节
- static代码块也叫静态代码块,作用就是对类进行初始化,而且他随着类的加载而执行,并且只会执行一次,如果是普通代码块,每创建一个对象就会执行一次
- 类什么时候会被加载
- 创建对象实例时(new)
- 创建子类对象实例,父类也会被加载
- 使用类的静态成员时(静态属性、静态方法)
- 普通的代码块,在创建对象实例时,会被隐式的调用,被创建一次就会调用一次;如果只是使用类的静态成员时,普通代码块并不会执行
- 创建一个对象时,在一个类 调用顺序是:
- 调用静态代码块和静态属性初始化调用的优先级是一样的,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用
- 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性的初始化调用的优先级一样,如果有多个普通代码块和都哦个普通属性初始化,则按定义顺序调用)
- 调用构造方法
单例设计模式
- 所谓单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供取得其对象实例的方法
- 单例模式有两种方式:饿汉式、懒汉式
-
饿汉式
- 构造器私有化 →防止直接new
- 类的内部创建对象
- 向外暴露一个静态的公共方法
- 代码