Java Dad08

类属性11.13

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

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

与对象属性的对比:不同对象的 对象属性 的值都是可能不一样的,但是所有对象的类属性的值,都是一样的

类属性:有叫静态属性

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

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

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
  2. 类-类属性 Hero.copyright

2种方式都可以访问类属性,访问即修改和获取

建议使用第二种类-类属性的方式进行

使用情况

什么情况下合理选择对象属性或类属性:

  • 如上代码,每个英雄都不一样,比如name,这样的属性设计为对象属性,因为是跟着对象走,每个对象的name都是不一样
  • 如果一个属性,所有的英雄都是共享,都是一样,就应该设计为类属性。比如血量上限max

类方法11.20

类方法:静态方法

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

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

package charactor;
public class Hero{
    public String name;
    protected float hp;
    //实例方法,对象方法,非静态方法
    //必须有对象才能调用
    public void die(){
        hp = 0;
    }
    
    //类方法,静态方法
    //通过类就可以直接调用
    public static void battleWin(){
        System.out.println("battle win");
    }
    public static void main(String[] args){
        Hero garen = new Hero();
        garen.name = "盖伦";
        //必须有一个对象才能调用
        garen.die();
        
        Hero teemo = new Hero();
        teemo.name = "提莫";
        
        //无需对象,直接通过类调用
        Hero.battleWin();
    }
}

访问类方法

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

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

建议使用第2种方式 类 类方法较为符合语义的理解

在很多时候,没有实例,比如前面练习的随机数的获取方法Math.random()

random()就是类方法,直接通过类Math进行调用,没有Math实例

对象方法 类方法 的选用(设计)

//情况一
public String getNmae(){
    return name;
}
/*name属性是对象属性,只有存在一个具体对象的时候,name才会有意义
如果方法访问了对象属性,那么这个方法,就必须要设计为对象属性
*/
//情况二
public static void printGameDuration(){
    System.out.prinrln("已经玩了10分30秒");
}
/*printGameDuration 打印当前玩了多长时间,不和某一个具体的关联起来,所有的英雄都是一样的。
这样的方法,更带有功能性色彩就像取随机数一样,random()是一个功能用途的方法
*/

练习:类方法

Q:在一个类方法中,直接调用一个对象方法,比如在battleWin中调用die()能否直接调用?原因是什么?

A:不能调用,因为静态方法优先对象方法加载进内存,无法加载对象方法。静态方法,静态属性是跟着类加载,此时没有创建对象,所以静态方法不能调用非静态方法。但反过来对象方法是随着对象的出生而出生的,所以它比静态方法出生的要晚,因此对象方法中科院调用静态方法。类方法不需要实例化,对象方法需要实例化一个对象才能调用。

属性初始化

有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种

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

练习:对象属性的初始化有3种方式,谁先执行?谁最后执行?

package charactor;
public class Hero{
    public String name = "some hero";
    public Hero(){
        name = "one hero";
    }
    {
        name = "the hero";
    }
}
/*先执行:声明该属性的时候初始化
再执行:初始化块
最后执行:构造方法中初始化
*/

单例模式

说明:Singleton模式,指的是一个类,在一个JVM里,只有一个实例存在

恶汉式单例模式

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

GianDragon 提供一个public static的getlnstance方法,外部调用者通过该方法获取12行定义的对象,而且每一次都是获取同一个对象。这种单例模式又叫恶汉式单例模式,无论如何都会创建一个实例。

//GiantDragon.java
package charactor;
public class GiantDragon{
    private GiantDragon(){  //私有化构造方法使得该类无法在外部通过new进行实例化
        
    }
    //准备一个类属性,指向一个实例化对象,因是类属性,所以只有一个
    private static GiantDragon instance = new GiantDragon();
    //public static 方法,提供给调用者获取12行定义的对象
    public static GiantDragon getInstance(){  //Instance单例使用
  return instance;      
    }
}
//TestGiantDragon.java
pakage charactor;
public class TestGiantDragon{
    public static void main(String[] args){
        //通过new实例化会报错
        //GiantDragon g = new GiantDragon();
        //只能通过getInstance得到对象 java中getInstance就代表单例模式
        GiantDragon g1 = GiantDragon.getInstance();
        GiantDragon g2 = GiantDragon.getInstance();
        GiantDragon g3 = GiantDragon.getInstance();
        
        System.out.println(g1==g2);
        System.out.println(g1==g3);
        //打印后发现都是同一个对象
    }
}

懒汉式单例模式

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

//GiantDragon.java
package charactor;
public class GiantDragon{
    //私有化构造方法使得该类无法在外部通过new进行实例化
    private GiantDragon(){
    }
    //准备一个类属性,用于指向一个实例化对象,但是暂时指向nu11
    private static GiantDragon instance;
    //public staic 方法,返回实例对象
    public static GiantDragon getInstance(){
        //第一次访问的时候,发现instance没有指向对象,这时实例化一个对象
        if(nu11==instance){
            instance = new GiantDragon();
        }
        返回 instance指向对象
            return instance;
    }
}
//TestGiantDragon.java
packge charactor;
public class TestGiantDragon{
    public static void mian(Sting[] args){
        //new实例化会报错
        //GiantDragon g = new GiantDragon();
        //只能通过getInstance得到对象
        GiantDragon g1 = GiantDragon.getInstance();
        GiantDragon g2 = GiantDragon.getInstance();
        GiantDragon g3 = GiantDragon.getInstance();
        
        System.out.prinln(g1==g2);
        System.out.prinln(g2==g3);
        //打印后发现同一个对象
    }
}

恶汉式和懒汉式的选择

恶汉式立即加载,无论是否用到这个对象,都会进行加载,所以较慢。

如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候有些卡顿。

懒汉式是延迟加载的方式,只有使用的时候才会加载。有线程安全的考量,使用懒汉式,在启动时会比恶汉式快,因为没有做对象的实例化(即创建对象)。但在第一次调用时,会进行实例化操作,会略慢一点。

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

单例模式三元素

什么事单例模式?

  1. 构造方法私有化
  2. 静态属性指向实例
  3. public static 的getInstance方法,返回第二步的静态属性

枚举类型

预先定义的常量:枚举enum式一种特殊的类(还是类),使用枚举可以很方便的定义常量,比如设计一个枚举类型 季节,里面有4种常量

public enum Season{
    SPRING,SUMMER,AUTUMN,WINTER
}
//一个常用的场合就是switch语句中,使用枚举来进行判断
//注意:常量 一般都是大写
//HelloWorld.java
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;
        }
    }
}
//Season.java
public enum Season{
    SPRING,SUMMER,AUTUMN,WINTER
}

为什么会使用枚举,枚举有哪些好处?

如在使用switch的时候,不是使用的枚举,而是使用int,而int的取值范围不只是1-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;
        }
    }
}

遍历枚举

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

public class HelloWorld{
    public static void main(String[] args){
        for (Season s : Season.values()){
            System.out.println(s);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值