一、类和对象

1.创建类

LOL有很多英雄,比如盲僧,团战可以输,提莫必须死,盖伦,琴女
所有这些英雄,都有一些共同的状态
比如,他们都有名字,hp,护甲,移动速度等等
这样我们就可以设计一种东西,叫做类,代表英雄这样一种事物
类: 英雄(Hero)
状态: 名字, 血量,护甲,移动速度

class Hero {
    String name; //姓名
    float hp; //血量
    float armor; //护甲
    int moveSpeed; //移动速度
}

2.创建对象

类就像一个模板,根据这样一个模板,可以创建一个个的具体的英雄
一个个具体的英雄,就叫一个个的对象
new Hero() 就是java中创建一个英雄对象的意思

public class MAIN {
    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.命名规范

好的编程习惯会让代码看上去更清爽,易读,容易维护
(1)类的第一个字母大写,如:Hero()

(2)驼峰原则 ,如:NewHero()

二、属性

一个英雄有姓名,血量,护甲等等状态
这些状态就叫做一个类的属性

1.基本类型

类型

缺省值

长度

数的范围

整型

byte

0

8位

-128~127

short

0

16位

-32768~32767

int

0

32位

long

0

64位

字符型

char

16位

浮点型

float

0.0

32位

3.4E-038~3.4E+038

double

0.0

64位

1.7E-308~1.7E+308

布尔型

boolean

false

1位

false、true

注意: 默认的小数值是double类型的
所以 float f = 54.321会出现编译错误,因为54.321的默认类型是 double,其类型 长度为64,超过了float的长度32
在数字后面加一个字母f,直接把该数字声明成float类型
float f2 = 54.321f,
这样就不会出错了

2.属性的类型

属性的类型可以是基本类型,比如int整数,float 浮点数
也可以是类类型,比如String 字符串

3.命名规范

(1)变量命名只能使用字母 数字 $ _
        变量第一个字符 只能使用 字母 $ _
        变量第一个字符 不能使用数字
        注:_ 是下划线,不是-减号或者—— 破折号

(2)在命名的时候,尽量使用完整的单词进行命名,比如name,moveSpeed,而不是使用缩写 n,m。

(3)不能只使用关键字,但是可以包含关键字

Java写英雄属性方法_构造方法

(4)中文也是可以用来命名变量的,但是在实际工作中。。。别这么干。。。

三、方法

        在LOL中,一个英雄可以做很多事情,比如超神,超鬼,坑队友,能做什么在类里面就叫做方法,和函数差不多。

1.无返回值

        比如队友残血正在逃跑,你过去把路给别人挡住了,导致他被杀掉。 这就是坑队友,每个英雄。。。。都可以坑,所以为Hero这个类,设计一个方法: keng

//坑队友
void keng(){
     System.out.println("坑队友!");
}

2.有返回值

        玩游戏的时候我们经常会查看英雄的状态,比如护甲

//获取护甲值
float getArmor(){
     return armor;
}

3.命名规则

动词开头的,比如 keng ...
        如果有多个单词,后面的每个单词的第一个字母使用大写,比如 addSpeed

四、引用

引用的概念,如果一个变量的类型是 类类型,而非基本类型,那么该变量又叫做引用。

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

        Hero h = new Hero();        h这个变量是Hero类型,又叫做引用;=的意思指的h这个引用代表右侧创建的对象,“代表” 在面向对象里,又叫做“指向”

Java写英雄属性方法_java_02

 引用有多个,但是对象只有一个。

Java写英雄属性方法_开发语言_03

Java写英雄属性方法_类属性_04

 五、继承

        在LOL中物品有武器、防具、药品等,它们都具有物品类的名称和价格属性,因此在设计类的时候,可以让武器继承物品,从而继承名称和价格属性。

//定义物品类,包含名称和价格两个属性
class Item {
    String name;
    int price;
}

//定义武器类,使其继承物品类的名称和价格两个属性,同时增加攻击力属性
class Weapon extends Item{
    int damage; //攻击力    
}

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

六、方法重载

类型或个数不一样。

class Hero {
    String name; //姓名
    float hp; //血量
    float armor; //护甲
    int moveSpeed; //移动速度

    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 void attack(Hero... heros) {
    for (int i = 0; i < heros.length; i++) {
        System.out.println(name + " 攻击了 " + heros[i].name); 
    }
}

七、构造方法

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

1.什么是构造方法

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

class Hero {
    // 方法名和类名一样(包括大小写)
    // 没有返回类型
    public Hero() {
        System.out.println("实例化一个对象的时候,必然调用构造方法");
    }
}

2.隐式的构造方法

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

class Hero {
//如果不写,默认会有
//    public Hero() {
//    }
}

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

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

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;
    }   
}

八、this

        this即代表当前对象

public class Hero {
     
    String name; //姓名
 
    //参数名和属性名一样
    //在方法体中,只能访问到参数name
    public void setName1(String name){
        name = name;
    }
     
    //为了避免setName1中的问题,参数名不得不使用其他变量名
    public void setName2(String heroName){
        name = heroName;
    }
     
    //通过this访问属性
    public void setName3(String name){
        //name代表的是参数name
        //this.name代表的是属性name
        this.name = name;
    }   
}

九、访问修饰符

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

2.类间的关系
        自身:指的是Hero自己
        同包子类:ADHero这个类是Hero的子类,并且和Hero处于同一个包下
        不同包子类:Support这个类是Hero的子类,但是在另一个包下
        同包类: GiantDragon 这个类和Hero是同一个包,但是彼此没有继承关系
        其他类:Item这个类,在不同包,也没有继承关系的类

自身

同包子类

不同包子类

同包类

其他类

private

可访问

不可继承

不可继承

不可访问

不可访问

package

可访问

可继承

不可继承

可访问

不可访问

protected

可访问

可继承

可继承

可访问

不可访问

public

可访问

可继承

可继承

可访问

可访问

 3.那么什么情况该用什么修饰符呢?
        (1)属性通常使用private封装起来;
        (2)方法一般使用public用于被调用;
        (3)会被子类继承的方法,通常使用protected;
        (4)package用的不多,一般新手会用package,因为还不知道有修饰符这个东西。
        再就是作用范围最小原则
        简单说,能用private就用private,不行就放大一级,用package,再不行就用protected,最后用public。 这样就能把数据尽量的封装起来,没有必要露出来的,就不用露出来了。

十、类属性与类方法

1.类属性

        当一个属性被static修饰的时候,就叫做类属性,又叫做静态属性。当一个属性被声明成类属性,那么所有的对象,都共享一个值。
        与对象属性对比: 不同对象的对象属性的值都可能不一样,但是所有对象的类属性的值,都是一样的。

(1)访问类属性

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

//2. 类.类属性
Hero.copyright

类.类属性

(2)什么时候使用对象属性,什么时候使用类属性

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

2.类方法

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

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

(1)访问类方法

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

//2. 类.类方法
Hero.battleWin();

类.类方法

(2)什么时候设计对象方法,什么时候设计类方法

        如果方法里访问了对象属性,那么这个方法,就必须设计为对象方法;

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

十一、属性初始化

1. 对象属性初始化

        声明该属性的时候初始化
        构造方法中初始化
        初始化块

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

2.类属性初始化

        声明该属性的时候初始化
        静态初始化块

public class Hero {
    public String name;
    protected float hp;
    float maxHP;
     
    //物品栏的容量
    public static int itemCapacity=8; //声明的时候 初始化
     
    static{
        itemCapacity = 6;//静态初始化块 初始化
    }     
}

十二、单例模式

        单例模式又叫做 Singleton模式,指的是一个类,在一个JVM里,只有一个实例存在。例如LOL里有一个怪叫大龙GiantDragon,只有一只,所以该类,只能被实例化一次

1.饿汉式单例模式

私有化其构造方法,使得外部无法通过new 得到新的实例。
        GiantDragon 提供了一个public static的getInstance方法,外部调用者通过该方法获取定义的对象,而且每一次都是获取同一个对象。 从而达到单例的目的。
        这种单例模式又叫做饿汉式单例模式,无论如何都会创建一个实例。

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

2.懒汉式单例模式

调用getInstance的时候,才会创建实例。

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

3.什么时候使用饿汉式,什么时候使用懒汉式

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

        懒汉式,是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量。
        使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。

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

4.单例模式三元素

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

十三、枚举

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

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

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

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

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;
}

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