类与对象

文章目录

  • 类与对象
    • 1. 引用
      • 步骤 1 : 引用和指向
      • 步骤 2 : 多个引用,一个对象
      • 步骤 3 : 一个引用,多个对象
      • 步骤 4 : 练习-引用
    • 2. 继承
      • 步骤 1 : 物品类Item
      • 步骤 2 : 武器类Weapon(不继承)
      • 步骤 3 : 武器类Weapon(继承类Item)
    • 3. 方法重载
      • 步骤 1 : attack方法的重载
      • 步骤 2 : 可变数量的参数
    • 4. 构造方法
      • 步骤 1 : 什么是构造方法
      • 步骤 2 : 隐式的构造方法
      • 步骤 3 : 如果提供了一个有参的构造方法
      • 步骤 4 : 构造方法的重载
    • 5. this
      • 步骤 1 : this代表当前对象
      • 步骤 2 : 通过this访问属性
      • 步骤 3 : 通过this调用其他的构造方法
    • 6. 传参
      • 步骤 1 : 基本类型传参
      • 步骤 2 : 引用与=
      • 步骤 3 : 类类型传参
    • 7. 包
      • 步骤 1 : 把比较接近的类,规划在同一个包下
      • 步骤 2 : 使用其他包下的类,必须import
    • 8. 访问修饰符
      • 示例 1 : 类之间的关系
      • 示例 2 : private 私有的
      • 示例 3 : package/friendly/default 不写
      • 示例 4 : protected 受保护的
      • 示例 5 : public 公共的
      • 示例 6 : 总结
      • 示例 7 : 那么什么情况该用什么修饰符呢?
    • 9. 类属性
      • 步骤 1 : 类属性
      • 步骤 2 : 访问类属性
      • 步骤 3 : 什么时候使用对象属性,什么时候使用类属性
    • 10. 类方法
      • 步骤 1 : 类方法
      • 步骤 2 : 调用类方法
      • 步骤 3 : 什么时候设计对象方法,什么时候设计类方法
    • 11. 属性初始化
      • 步骤 1 : 对象属性初始化
      • 步骤 2 : 类属性初始化
    • 12. 单例模式
      • 步骤 1 : 单例模式
      • 步骤 2 : 饿汉式单例模式
      • 步骤 3 : 懒汉式单例模式
      • 步骤 4 : 什么时候使用饿汉式,什么时候使用懒汉式
      • 步骤 5 : 单例模式三元素
    • 13. 枚举类型
      • 步骤 1 : 预先定义的常量
      • 步骤 2 : 使用枚举的好处
      • 步骤 3 : 遍历枚举

1. 引用

步骤 1 : 引用和指向

new Hero();

代表创建了一个Hero对象但是也仅仅是创建了一个对象,没有办法访问它为了访问这个对象,会使用引用来代表这个对象

Hero h = new Hero();

h这个变量是Hero类型,又叫做引用
=的意思指的h这个引用代表右侧创建的对象
“代表” 在面向对象里,又叫做“指向”[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zY0qEn1Y-1599114930145)(en-resource://database/930:1)]

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度public static void main(String[] args) {//创建一个对象new Hero();//使用一个引用来指向这个对象Hero h = new Hero();}  }

步骤 2 : 多个引用,一个对象

引用有多个,但是对象只有一个。
在这个例子里,所有引用都指向了同一个对象。
对象就像 “房产”, 引用就像"房产证"
房产证的复印件可以有多张,但是真正的"房产" 只有这么一处[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yEYLIMXJ-1599114930159)(en-resource://database/932:1)]

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度public static void main(String[] args) {//使用一个引用来指向这个对象Hero h1 = new Hero();Hero h2 = h1;  //h2指向h1所指向的对象Hero h3 = h1;Hero h4 = h1;Hero h5 = h4;//h1,h2,h3,h4,h5 五个引用,都指向同一个对象}  }

步骤 3 : 一个引用,多个对象

第8行,引用garen指向新创建的对象(对象1)
第9行,同一个引用garen指向新创建的对象(对象2)这个时候,对象1,就没有任何引用指向了换句话说,就没有任何手段控制和访问该对象,那么该对象就变得没有意义。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TjMgA74S-1599114930164)(en-resource://database/934:1)]

package charactor;public class Hero {public String name;protected float hp;public static void main(String[] args) {Hero garen =  new Hero();garen =  new Hero();}
}

步骤 4 : 练习-引用

如代码,问题:h4所指向的对象和h2所指向的对象,是否是同一个对象?

package charactor;public class Hero {public String name;protected float hp;public static void main(String[] args) {Hero h1 =  new Hero();Hero h2 =  new Hero();Hero h3;Hero h4;h3 = h1;h4 = h3;}
}

如果所示,h4指向h3,最终间接地指向了对象1而h2指向的是对象2,所以h4和h2不是指向同一个对象[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MAfbcVzX-1599114930168)(en-resource://database/936:1)]

2. 继承

在LOL中,武器是物品的一种,也是有名称和价格的所以在设计类的时候,可以让武器继承物品,从而继承名称和价格属性

步骤 1 : 物品类Item

物品类Item 有属性 name,price

public class Item {String name;int price;
}

步骤 2 : 武器类Weapon(不继承)

武器类: Weapon不继承Item的写法
独立设计 name和price属性
同时多了一个属性 damage 攻击力

public class Weapon{String name;int price;int damage; //攻击力}

步骤 3 : 武器类Weapon(继承类Item)

这一次Weapon继承Item虽然Weapon自己没有设计name和price,但是通过继承Item类,也具备了name和price属性

public class Weapon extends Item{int damage; //攻击力public static void main(String[] args) {Weapon infinityEdge = new Weapon();infinityEdge.damage = 65; //damage属性在类Weapon中新设计的infinityEdge.name = "无尽之刃";//name属性,是从Item中继承来的,就不需要重复设计了infinityEdge.price = 3600;}}

3. 方法重载

方法的重载指的是方法名一样,但是参数类型不一样

步骤 1 : attack方法的重载

有一种英雄,叫做物理攻击英雄 ADHero为ADHero 提供三种方法

public void attack()
public void attack(Hero h1)
public void attack(Hero h1, Hero h2)

方法名是一样的,但是参数类型不一样在调用方法attack的时候,会根据传递的参数类型以及数量,自动调用对应的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K0D40o9L-1599114930172)(en-resource://database/942:1)]

public class ADHero extends Hero {public void attack() {System.out.println(name + " 进行了一次攻击 ,但是不确定打中谁了");}public void attack(Hero h1) {System.out.println(name + "对" + h1.name + "进行了一次攻击 ");}public void attack(Hero h1, Hero h2) {System.out.println(name + "同时对" + h1.name + "和" + h2.name + "进行了攻击 ");}public static void main(String[] args) {ADHero bh = new ADHero();bh.name = "赏金猎人";Hero h1 = new Hero();h1.name = "盖伦";Hero h2 = new Hero();h2.name = "提莫";bh.attack(h1);bh.attack(h1, h2);}}

步骤 2 : 可变数量的参数

如果要攻击更多的英雄,就需要设计更多的方法,这样类会显得很累赘,像这样:

public void attack(Hero h1)
public void attack(Hero h1,Hero h2)
public void attack(Hero h1,Hero h2,Hero h3)

这时,可以采用可变数量的参数只需要设计一个方法

public void attack(Hero ...heros)

即可代表上述所有的方法了在方法里,使用操作数组的方式处理参数heros即可

public class ADHero extends Hero {public void attack() {System.out.println(name + " 进行了一次攻击 ,但是不确定打中谁了");}// 可变数量的参数public void attack(Hero... heros) {for (int i = 0; i < heros.length; i++) {System.out.println(name + " 攻击了 " + heros[i].name);}}public static void main(String[] args) {ADHero bh = new ADHero();bh.name = "赏金猎人";Hero h1 = new Hero();h1.name = "盖伦";Hero h2 = new Hero();h2.name = "提莫";bh.attack(h1);bh.attack(h1, h2);}}

4. 构造方法

通过一个类创建一个对象,这个过程叫做实例化实例化是通过调用构造方法(又叫做构造器)实现的

步骤 1 : 什么是构造方法

方法名和类名一样(包括大小写)
没有返回类型
实例化一个对象的时候,必然调用构造方法

public class Hero {String name;float hp;float armor;int moveSpeed;// 方法名和类名一样(包括大小写)// 没有返回类型public Hero() {System.out.println("实例化一个对象的时候,必然调用构造方法");}public static void main(String[] args) {//实例化一个对象的时候,必然调用构造方法Hero h = new Hero();}}

步骤 2 : 隐式的构造方法

Hero类的构造方法是

public Hero(){}

这个无参的构造方法,如果不写,就会默认提供一个

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度//这个无参的构造方法,如果不写,//就会默认提供一个无参的构造方法//  public Hero(){ //      System.out.println("调用Hero的构造方法");//  }public static void main(String[] args) {Hero garen =  new Hero();garen.name = "盖伦";garen.hp = 616.28f;garen.armor = 27.536f;garen.moveSpeed = 350;Hero teemo =  new Hero();teemo.name = "提莫";teemo.hp = 383f;teemo.armor = 14f;teemo.moveSpeed = 330;}  }

步骤 3 : 如果提供了一个有参的构造方法

一旦提供了一个有参的构造方法
同时又没有显式的提供一个无参的构造方法
那么默认的无参的构造方法,就“木有了“

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度//有参的构造方法//默认的无参的构造方法就失效了public Hero(String heroname){ name = heroname;}public static void main(String[] args) {Hero garen =  new Hero("盖伦"); Hero teemo =  new Hero(); //无参的构造方法“木有了”}  }

步骤 4 : 构造方法的重载

和普通方法一样,构造方法也可以重载

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度//带一个参数的构造方法public Hero(String heroname){ name = heroname;}//带两个参数的构造方法public Hero(String heroname,float herohp){ name = heroname;hp = herohp;}public static void main(String[] args) {Hero garen =  new Hero("盖伦"); Hero teemo =  new Hero("提莫",383);}}

5. this

this这个关键字,相当于普通话里的“我”
小明说 “我吃了” 这个时候,“我” 代表小明
小红说 “我吃了” 这个时候,“我” 代表小红
"我"代表当前人物this这个关键字,相当于普通话里的“我”
this即代表当前对象

步骤 1 : this代表当前对象

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度//打印内存中的虚拟地址public void showAddressInMemory(){System.out.println("打印this看到的虚拟地址:"+this);}public static void main(String[] args) {Hero garen =  new Hero();garen.name = "盖伦";//直接打印对象,会显示该对象在内存中的虚拟地址//格式:Hero@c17164 c17164即虚拟地址,每次执行,得到的地址不一定一样System.out.println("打印对象看到的虚拟地址:"+garen);//调用showAddressInMemory,打印该对象的this,显示相同的虚拟地址garen.showAddressInMemory();Hero teemo =  new Hero();teemo.name = "提莫";System.out.println("打印对象看到的虚拟地址:"+teemo);teemo.showAddressInMemory();}  }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T3i9BRar-1599114930175)(en-resource://database/1269:1)]

步骤 2 : 通过this访问属性

通过this关键字访问对象的属性

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度//参数名和属性名一样//在方法体中,只能访问到参数namepublic void setName1(String name){name = name;}//为了避免setName1中的问题,参数名不得不使用其他变量名public void setName2(String heroName){name = heroName;}//通过this访问属性public void setName3(String name){//name代表的是参数name//this.name代表的是属性namethis.name = name;}public static void main(String[] args) {Hero  h =new Hero();h.setName1("teemo");System.out.println(h.name);h.setName2("garen");System.out.println(h.name);    h.setName3("死歌");System.out.println(h.name);    }}

步骤 3 : 通过this调用其他的构造方法

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度//带一个参数的构造方法public Hero(String name){System.out.println("一个参数的构造方法");this.name = name;}//带两个参数的构造方法public Hero(String name,float hp){this(name);System.out.println("两个参数的构造方法");this.hp = hp;}public static void main(String[] args) {Hero teemo =  new Hero("提莫",383);System.out.println(teemo.name);}}

6. 传参

变量有两种类型 基本类型 和类类型
参数也是变量,所以传参分为
基本类型传参
类类型传参

步骤 1 : 基本类型传参

基本类型传参在方法内,无法修改方法外的基本类型参数

public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度public Hero(){}//回血public void huixue(int xp){hp = hp + xp;//回血完毕后,血瓶=0xp=0;}public Hero(String name,float hp){this.name = name;this.hp = hp;}public static void main(String[] args) {Hero teemo =  new Hero("提莫",383);//血瓶,其值是100int xueping = 100;//提莫通过这个血瓶回血teemo.huixue(xueping);System.out.println(xueping);}}

步骤 2 : 引用与=

如果一个变量是基本类型比如 int hp = 50;
我们就直接管hp叫变量=表示赋值的意思。
如果一个变量是类类型比如 Hero h = new Hero();
我们就管h叫做引用。
=不再是赋值的意思
=表示指向的意思
比如 Hero h = new Hero();
这句话的意思是引用h,指向一个Hero对象

步骤 3 : 类类型传参

类类型又叫引用
第24行的引用 teemo与 第17行的引用hero,是不同的引用
通过调用garen.attack(teemo, 100); 使得这两个引用都指向了同一个对象
所以在第18行hero.hp = hero.hp - damage; 就使得该对象的hp值,发生了变化
因此第25行,打印该对象的Hp值就是变化后的值

public class Hero {String name; // 姓名float hp; // 血量float armor; // 护甲int moveSpeed; // 移动速度public Hero(String name, float hp) {this.name = name;this.hp = hp;}// 攻击一个英雄,并让他掉damage点血public void attack(Hero hero, int damage) {hero.hp = hero.hp - damage;}public static void main(String[] args) {Hero teemo = new Hero("提莫", 383);Hero garen = new Hero("盖伦", 616);garen.attack(teemo, 100);System.out.println(teemo.hp);}}

7. 包

包: package
把比较接近的类,规划在同一个包下

步骤 1 : 把比较接近的类,规划在同一个包下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6AlURq5w-1599114930177)(en-resource://database/1271:1)]

package charactor; //在最开始的地方声明该类所处于的包名
public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度}

步骤 2 : 使用其他包下的类,必须import

使用同一个包下的其他类,直接使用即可
但是要使用其他包下的类,必须import

package charactor;//Weapon类在其他包里,使用必须进行import
import property.Weapon;public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度//装备一把武器public void equip(Weapon w){}}

8. 访问修饰符

成员变量有四种修饰符
private 私有的
package/friendly/default 不写
protected 受保护的
public 公共的

比如public 表示公共的

public String name;

而maxHP 没有修饰符即代package/friendly/default

float maxHP

示例 1 : 类之间的关系

类和类之间的关系有如下几种:
以Hero为例

自身:指的是Hero自己

同包子类:ADHero这个类是Hero的子类,并且和Hero处于同一个包下

不同包子类:Support这个类是Hero的子类,但是在另一个包下

同包类: GiantDragon 这个类和Hero是同一个包,但是彼此没有继承关系

其他类:Item这个类,在不同包,也没有继承关系的类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-th34iBZf-1599114930178)(en-resource://database/1273:1)]

示例 2 : private 私有的

使用private修饰属性
自身:是可以访问的
同包子类:不能继承
不同包子类:不能继承
同包类:不能访问
其他包类:不能访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-97fF5bvL-1599114930179)(en-resource://database/1275:1)]

package charactor;import property.Weapon;public class Hero {//属性id是private的,只有Hero自己可以访问//子类不能继承//其他类也不能访问private int id;String name;float hp;float armor;int moveSpeed;public void equip(Weapon w) {}}

示例 3 : package/friendly/default 不写

没有修饰符即代表package/friendly/defaultfloat maxHP; 血量上限
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eJbyW58a-1599114930180)(en-resource://database/1277:1)]

package charactor;import property.Weapon;public class Hero {private int id;String name;// 无修饰符的属性 hp// 自己可以访问// 同包子类可以继承// 不同包子类不能继承// 同包类可以访问// 不同包类不能访问float hp;float armor;int moveSpeed;public void equip(Weapon w) {}}

示例 4 : protected 受保护的

受保护的修饰符protected float hp; 血量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gn4kHDTB-1599114930181)(en-resource://database/1279:1)]

注: 红色字体,表示不可行

package charactor;import property.Weapon;public class Hero {private int id;String name;// protected饰符的属性 hp// 自己可以访问// 同包子类可以继承// 不同包子类可以继承// 同包类可以访问// 不同包类不能访问protected float hp;float armor;int moveSpeed;public void equip(Weapon w) {}}

示例 5 : public 公共的

公共的修饰符
public String name; 姓名
任何地方,都可以访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fms5P3Yd-1599114930183)(en-resource://database/1281:1)]

package charactor;import property.Weapon;public class Hero {private int id;// public的属性 name// 自己可以访问// 同包子类可以继承// 不同包子类可以继承// 同包类可以访问// 不同包类可以访问public String name;protected float hp;float armor;int moveSpeed;public void equip(Weapon w) {}}

示例 6 : 总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uUNhsSVJ-1599114930184)(en-resource://database/1283:1)]

示例 7 : 那么什么情况该用什么修饰符呢?

那么什么情况该用什么修饰符呢?
从作用域来看,public能够使用所有的情况。 但是大家在工作的时候,又不会真正全部都使用public,那么到底什么情况该用什么修饰符呢?

  1. 属性通常使用private封装起来
  2. 方法一般使用public用于被调用
  3. 会被子类继承的方法,通常使用protected
  4. package用的不多,一般新手会用package,因为还不知道有修饰符这个东西

再就是 作用范围最小原则
简单说,能用private就用private,不行就放大一级,用package,再不行就用protected,最后用public。 这样就能把数据尽量的封装起来,没有必要露出来的,就不用露出来了

9. 类属性

当一个属性被static修饰的时候,就叫做类属性,又叫做静态属性

当一个属性被声明成类属性,那么所有的对象,都共享一个值

与对象属性对比:
不同对象的 对象属性 的值都可能不一样。
比如盖伦的hp 和 提莫的hp 是不一样的。
但是所有对象的类属性的值,都是一样的

步骤 1 : 类属性

类属性: 又叫做静态属性
对象属性: 又叫实例属性,非静态属性

如果一个属性声明成类属性,那么所有的对象,都共享这么一个值给英雄设置一个类属性叫做“版权" (copyright), 无论有多少个具体的英雄,所有的英雄的版权都属于 Riot Games公司

package charactor;public class Hero {public String name; //实例属性,对象属性,非静态属性protected float hp;static String copyright;//类属性,静态属性public static void main(String[] args) {Hero garen =  new Hero();garen.name = "盖伦";Hero.copyright = "版权由Riot Games公司所有";System.out.println(garen.name);System.out.println(garen.copyright);Hero teemo =  new Hero();teemo.name = "提莫";System.out.println(teemo.name);    System.out.println(teemo.copyright);}}

步骤 2 : 访问类属性

访问类属性有两种方式

  1. 对象.类属性
teemo.copyright
  1. 类.类属性
Hero.copyright

这两种方式都可以访问类属性,访问即修改和获取,但是建议使用第二种 类.类属性 的方式进行,这样更符合语义上的理解

步骤 3 : 什么时候使用对象属性,什么时候使用类属性

如果一个属性,每个英雄都不一样,比如name,这样的属性就应该设计为对象属性,因为它是跟着对象走的,每个对象的name都是不同的

如果一个属性,所有的英雄都共享,都是一样的,那么就应该设计为类属性。比如血量上限,所有的英雄的血量上限都是 9999,不会因为英雄不同,而取不同的值。 这样的属性,就适合设计为类属性

10. 类方法

类方法: 又叫做静态方法

对象方法: 又叫实例方法,非静态方法

访问一个对象方法,必须建立在有一个对象的前提的基础上访问类方法,不需要对象的存在,直接就访问

步骤 1 : 类方法

类方法: 又叫做静态方法

对象方法: 又叫实例方法,非静态方法

访问一个对象方法,必须建立在有一个对象的前提的基础上访问类方法,不需要对象的存在,直接就访问

步骤 2 : 调用类方法

和访问类属性一样,调用类方法也有两种方式

  1. 对象.类方法
garen.battleWin();
  1. 类.类方法
Hero.battleWin();

这两种方式都可以调用类方法,但是建议使用第二种 类.类方法 的方式进行,这样更符合语义上的理解。并且在很多时候,并没有实例,比如在前面练习的时候用到的随机数的获取办法

Math.random()

random()就是一个类方法,直接通过类Math进行调用,并没有一个Math的实例存在。

步骤 3 : 什么时候设计对象方法,什么时候设计类方法

如果在某一个方法里,调用了对象属性,比如

public String getName(){return name;
}

name属性是对象属性,只有存在一个具体对象的时候,name才有意义。 如果方法里访问了对象属性,那么这个方法,就必须设计为对象方法

如果一个方法,没有调用任何对象属性,那么就可以考虑设计为类方法,比如

public static void printGameDuration(){System.out.println("已经玩了10分50秒");
}

printGameDuration 打印当前玩了多长时间了,不和某一个具体的英雄关联起来,所有的英雄都是一样的。 这样的方法,更带有功能性色彩就像取随机数一样,random()是一个功能用途的方法

Math.random()

11. 属性初始化

步骤 1 : 对象属性初始化

对象属性初始化有3种

  1. 声明该属性的时候初始化
  2. 构造方法中初始化
  3. 初始化块
package charactor;public class Hero {public String name = "some hero"; //声明该属性的时候初始化protected float hp;float maxHP;{maxHP = 200; //初始化块}  public Hero(){hp = 100; //构造方法中初始化}}

步骤 2 : 类属性初始化

类属性初始化有2种

  1. 声明该属性的时候初始化
  2. 静态初始化块
package charactor;public class Hero {public String name;protected float hp;float maxHP;//物品栏的容量public static int itemCapacity=8; //声明的时候 初始化static{itemCapacity = 6;//静态初始化块 初始化}public Hero(){}public static void main(String[] args) {System.out.println(Hero.itemCapacity);}}


对象属性的初始化有三种方式故意把初始化块,放在构造方法下面,问题:这三种方式,谁先执行?谁后执行?

package charactor;public class Hero {public String name = "some hero"; public Hero(){name = "one hero";}{name = "the hero";}}

声明 块 构造方法 one hero

12. 单例模式

LOL里有一个怪叫大龙GiantDragon,只有一只,所以该类,只能被实例化一次

步骤 1 : 单例模式

单例模式又叫做 Singleton模式,指的是一个类,在一个JVM里,只有一个实例存在。

步骤 2 : 饿汉式单例模式

GiantDragon 应该只有一只,通过私有化其构造方法,使得外部无法通过new 得到新的实例。

GiantDragon 提供了一个public static的getInstance方法,外部调用者通过该方法获取12行定义的对象,而且每一次都是获取同一个对象。 从而达到单例的目的。

这种单例模式又叫做饿汉式单例模式,无论如何都会创建一个实例


package charactor;public class GiantDragon {//私有化构造方法使得该类无法在外部通过new 进行实例化private GiantDragon(){}//准备一个类属性,指向一个实例化对象。 因为是类属性,所以只有一个private static GiantDragon instance = new GiantDragon();//public static 方法,提供给调用者获取12行定义的对象public static GiantDragon getInstance(){return instance;}}

package charactor;public class TestGiantDragon {public static void main(String[] args) {//通过new实例化会报错
//      GiantDragon g = new GiantDragon();//只能通过getInstance得到对象GiantDragon g1 = GiantDragon.getInstance();GiantDragon g2 = GiantDragon.getInstance();GiantDragon g3 = GiantDragon.getInstance();//都是同一个对象System.out.println(g1==g2);System.out.println(g1==g3);}
}

步骤 3 : 懒汉式单例模式

懒汉式单例模式与饿汉式单例模式不同,只有在调用getInstance的时候,才会创建实例

package charactor;public class GiantDragon {//私有化构造方法使得该类无法在外部通过new 进行实例化private GiantDragon(){       }//准备一个类属性,用于指向一个实例化对象,但是暂时指向nullprivate static GiantDragon instance;//public static 方法,返回实例对象public static GiantDragon getInstance(){//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象if(null==instance){instance = new GiantDragon();}//返回 instance指向的对象return instance;}}package charactor;public class GiantDragon {//私有化构造方法使得该类无法在外部通过new 进行实例化private GiantDragon(){       }//准备一个类属性,用于指向一个实例化对象,但是暂时指向nullprivate static GiantDragon instance;//public static 方法,返回实例对象public static GiantDragon getInstance(){//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象if(null==instance){instance = new GiantDragon();}//返回 instance指向的对象return instance;}}

package charactor;public class TestGiantDragon {public static void main(String[] args) {//通过new实例化会报错
//      GiantDragon g = new GiantDragon();//只能通过getInstance得到对象GiantDragon g1 = GiantDragon.getInstance();GiantDragon g2 = GiantDragon.getInstance();GiantDragon g3 = GiantDragon.getInstance();//都是同一个对象System.out.println(g1==g2);System.out.println(g1==g3);}
}

步骤 4 : 什么时候使用饿汉式,什么时候使用懒汉式

饿汉式是立即加载的方式,无论是否会用到这个对象,都会加载。如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候感觉稍微有些卡顿。

懒汉式,是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量(鉴于同学们学习的进度,暂时不对线程的章节做展开)。使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。

看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式

步骤 5 : 单例模式三元素

这个是面试的时候经常会考的点,面试题通常的问法是:
什么是单例模式?

回答的时候,要答到三元素

  1. 构造方法私有化

  2. 静态属性指向实例

  3. public static的 getInstance方法,返回第二步的静态属性

13. 枚举类型

步骤 1 : 预先定义的常量

枚举enum是一种特殊的类(还是类),使用枚举可以很方便的定义常量

比如设计一个枚举类型 季节,里面有4种常量

public enum Season {SPRING,SUMMER,AUTUMN,WINTER
}

一个常用的场合就是switch语句中,使用枚举来进行判断

注:因为是常量,所以一般都是全大写

public class HelloWorld {public static void main(String[] args) {Season season = Season.SPRING;switch (season) {case SPRING:System.out.println("春天");break;case SUMMER:System.out.println("夏天");break;case AUTUMN:System.out.println("秋天");break;case WINTER:System.out.println("冬天");break;}}
}

public enum Season {SPRING,SUMMER,AUTUMN,WINTER
}

步骤 2 : 使用枚举的好处

假设在使用switch的时候,不是使用枚举,而是使用int,而int的取值范围就不只是1-4,有可能取一个超出1-4之间的值,这样判断结果就似是而非了。(因为只有4个季节)

但是使用枚举,就能把范围死死的限定在这四个当中

SPRING,SUMMER,AUTUMN,WINTER

public class HelloWorld {public static void main(String[] args) {int season = 5;switch (season) {case 1:System.out.println("春天");break;case 2:System.out.println("夏天");break;case 3:System.out.println("秋天");break;case 4:System.out.println("冬天");break;}}
}

步骤 3 : 遍历枚举

借助增强型for循环,可以很方便的遍历一个枚举都有哪些常量

public class HelloWorld {public static void main(String[] args) {for (Season s : Season.values()) {System.out.println(s);}}
}

JavaSE笔记 类与对象相关推荐

  1. python入门笔记——类和对象⑤(继承)

    python入门笔记--类和对象⑤(继承) # python中展现面向对象的三大特征:封装.继承.多态 # 封装:把内容封装到某个地方以便后续的使用 # 对封装来说,其实就是使用初始化构造方法将内容封 ...

  2. Java实用教程笔记 类与对象(续)

    类与对象(续) 实例变量(动态变量) 类变量(静态变量)(数据共享)static(尽量写成public(private和protected毫无意义)) 实例方法(既可访问静态数据,又可访问动态数据)A ...

  3. Java实用教程笔记 类与对象

    类与对象 Abstract Body instanceof 文件后缀名 .py .c .cpp .java 成员函数/成员方法/行为 interface接口 可类比C++中抽象类 IDEA快捷键操作 ...

  4. (JAVA学习笔记) 类与对象小结

    1.类与对象 类是一个抽象的模板: 对象是类的一个具体的实例: 2.方法 方法的定义:修饰符,返回类型,方法名,参数列表,异常抛出,返回值. 方法的调用:静态方法,非静态方法,形参和实参,值传递和引用 ...

  5. java笔记类与对象3.7-3.10 2020.3.17

    List,是个接口 ArrayList才是动态数组类 3.7垃圾回收机制 this的三种用法 this(1,2,3)会调用构造器 下图三个对象都是垃圾对象 让系统回收垃圾对象 回收的时候,会调用自己的 ...

  6. 【JavaSE】类和对象

    文章目录 面向对象设计概述 认识类 类的定义格式 对象特征 类的实例化 类和对象的关系 自定义类 构造器 封装的优点 this关键字 final实例域 静态域和静态方法 静态域和静态成员变量 静态方法 ...

  7. Java 入门知识学习笔记 (类和对象)

    一.类和对象的定义及关系 1.类是同一类别对象的抽象定义:可以理解为是某一类具体对象的模子,确定对象将会拥有的特性,包括该类对象具备的属性和方法. 2.对象是对类的一种具体化的客观存在,是对类的具体实 ...

  8. 【JavaSE】类和对象 (二) —— 封装、包以及 static 关键字

    目录 1. 封装 1.1 封装的概念 1.2 访问限定符 2. 包 2.1 包的概念 2.2 导入包中的类 2.3 自定义包 2.3.1 包的基本规则 2.3.2 创建一个包 2.4 包访问权限--d ...

  9. java学习笔记-类与对象示例

    类与对象 环境 类和对象的概念 代码格式 实例化对象 调用方法 小游戏:王者solo赛 问题:如果有100个英雄呢? 继承 概念 格式 具体内容 子类可以继承到父类的哪些 方法重写: 自动转型: 优点 ...

最新文章

  1. linux 物理内存统计,说说free命令  + Linux可用内存统计方法
  2. python es 数据库_Python将json文件写入ES数据库的方法
  3. git使用-设置项目忽略文件
  4. 服务器监听端口信息,服务器监听端口信息
  5. 加载模型预测时出现Dst tensor is not initialized.
  6. Java中的垃圾回收与对象生命周期
  7. 2017 百度杯丶二月场第一周WP
  8. easyui input输入框的限制和校验条件
  9. R7-3 福到了 (10 分)
  10. UE4如何贴混合贴图_八猴,Unity,UE4,还原SubstancePainter贴图
  11. 重磅消息!Java之内存泄漏调试学习与总结,分享PDF高清版
  12. Go1.9 安全map用法
  13. ppt文字提取转word
  14. 王江民故事:38岁开始学计算机 与病毒作斗争
  15. YAPI部署及使用文档
  16. IP地址 归属地查询
  17. 美团到点事业部后台一二面经
  18. 帝国时代 游戏是如何开发的_开发人员是新的王国建设者
  19. antialiasing
  20. CSDN技能树实践测评:实践是检验真理的唯一标准

热门文章

  1. Coursera 吴恩达 DeepLearning Sequence model 第二周作业 Emojify - v2(多分类问题,有彩蛋,性能超过预期)
  2. c语言中rand是什么意思,c语言中Random是什么意思 random()的头文件是什么 - 云骑士一键重装系统...
  3. 程序员有用网站集(干货)
  4. SPW47N60C3-ASEMI代理英飞凌MOS管SPW47N60C3
  5. 计算机科学与技术专业考研视觉传达设计,视觉传达考研考什么 视觉传达考研方向...
  6. 含有吲哚基团132557-72-3,2,3,3-三甲基-3H-吲哚-5-磺酸
  7. 从虚机到容器,秒拍架构师告诉你如何平滑进行业务迁移
  8. Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
  9. VMware Ubuntu虚拟机忘记密码
  10. [Ahoi2009]Seq 维护序列seq