java饮品鉴赏

变量

  1. 当一个变量被声明在类下面
    变量就叫做字段 或者属性、成员变量、Field
    那么从第2行这个变量声明的位置开始,整个类都可以访问得到
    所以**其作用域就是从其声明的位置开始的整个类 **

  2. 声明在方法上就叫参数 or 局部变量
    其他方法和类中不能访问。

  3. final 给予唯一一次赋值,之后不可更改。还可用来修饰类和方法。

操作符

  1. 如果有任何运算单元的长度超过int,那么运算结果就按照最长的长度计算。
    比如:
    int a = 5;
    long b = 6;
    a+b; -> 结果类型是long 。

  2. 如果任何运算单元的长度都不超过int,那么运算结果就按照int来计算.
    byte a = 1;
    byte b= 2;
    a+b -> int 类型

  3. 与C++同样有% ++ –

  4. 长路与& 短路与&&
    长路与 无论第一个表达式的值是true或者false,第二个的值,都会被运算
    短路与 只要第一个表达式的值是false的,第二个表达式的值,就不需要进行运算了

  5. 长路或| 短路或||
    长路或 无论第一个表达式的值是true或者false,第二个的值,都会被运算
    短路或 只要第一个表达式的值是true的,第二个表达式的值,就不需要进行运算了

  6. 取非~ 带符号左移<< 带符号右移>> 无符号左移<<< 无符号右移>>>
    对二进制而言

  7. 异或^
    相同为零,不同为一。

  8. Integer.toBinaryString()一个整数的二进制表达式
    String b = (Integer.toBinaryString(i));

  9. Scanner
    Scanner s = new Scanner(System.in);
    float a = s.nextFloat();
    .nextFloat()读取浮点数
    .nextInt()读取整数
    .nextLine()读取字符串
    如果在业务上需要读取了整数后,接着读取字符串,那么就应该连续执行两次nextLine(),第一次是取走回车换行,第二次才是读取真正的字符串 。

 Scanner s = new Scanner(System.in);
        int i = s.nextInt();
        System.out.println("读取的整数是"+ i);
        String rn = s.nextLine();
        String a = s.nextLine();

控制语句

  1. outloop: 用标签结束外部循环(标签名为自定义的,可以是outloop1、out等等)
eg:
public class HelloWorld {
    public static void main(String[] args) {
        //打印单数    
        outloop: //outloop这个标示是可以自定义的比如outloop1,ol2,out5
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                System.out.println(i+":"+j);
                if(0==j%2) 
                    break outloop; //如果是双数,结束外部循环
            }
        }
    }
}
  1. debug 双击行数设置断点。
    断点表示马上就要运行断点行但还为运行。
    step over(f6)可以一行行执行代码

数组

  1. Math.random(),得到一个0-1之间的随机浮点数

  2. int a[] = new int[n]; 申明
    如果指定了数组的内容就不能同时设置数组的长度 int[] a = new int[]{100,101,102};

  3. 增强型for循环
    for (int each : values){
    System.out.println(each);
    }
    注:增强型for循环只能用来取值,却不能用来修改数组里的值

 eg:
int values [] = new int[]{18,62,68,82,65,9};
 
        //数组中的内容是
        for (int each : values) {
            System.out.print(each+" ");
        }
        System.out.println();
        int max = -1;
        for (int each : values) {
            if(each>max)
                max = each;
        }
         
        System.out.println("最大的一个值是:"+max);
  1. 复制数组
    System.arraycopy(src, srcPos, dest, destPos, length)
    src: 源数组
    srcPos: 从源数组复制数据的起始位置
    dest: 目标数组
    destPos: 复制到目标数组的起始位置
    length: 复制的长度

int[] b = Arrays.copyOfRange(a, 0, 3);
// copyOfRange(int[] original, int from, int to) // 第一个参数表示源数组
// 第二个参数表示开始位置(取得到)
// 第三个参数表示结束位置(取不到)

  1. 二维数组
    赋值方法:
    int[][] c = new int[][]{
    {1,2,4},
    {4,5},
    {6,7,8,9}
    };

  2. 打印数组
    content = Arrays.toString(a);
    直接把一个数组,转换为字符串,这样方便观察数组的内容

  3. 数组排序
    Arrays.sort(a);

  4. 搜索数组
    Arrays.binarySearch(数组,值)
    必须先排序。

  5. 判断是否相同
    Arrays.equals(a,b)
    比较两个数组的内容是否一样

  6. 填充
    Arrays.fill(数组,值)
    使用同一个值,填充整个数组
    copyOfRange
    数组复制

toString()
转换为字符串
sort
排序
binarySearch
搜索
equals
判断是否相同
fill
填充
需要引用库Arrays
import java.util.Arrays;

类和对象

  1. 引用
    创建:new Hero();
    引用:Hero h = new Hero();
    多重引用:
 		//使用一个引用来指向这个对象
        Hero h1 = new Hero();
        Hero h2 = h1;  //h2指向h1所指向的对象
        Hero h3 = h1;
        Hero h4 = h1;
        Hero h5 = h4; 
        //h1,h2,h3,h4,h5 五个引用,都指向同一				   
        个对象

一个引用同一时间只能指向一个对象

eg:
Hero h1 =  new Hero();
Hero h2 =  new Hero();
Hero h3;
Hero h4;
h3 = h1;
h4 = h3;

在这里插入图片描述
2. 继承
用Weapon继承Item:

public class Item {
    String name;
    int price;
}
public class Weapon extends Item{
    int damage; //攻击力
//他既有Item中的name和price属性,又有新添加的damage属性
}
  1. 构造方法
    方法名和类名一样(包括大小写),但没有返回类型。实例化一个对象的时候,必然调用构造方法。
    Hero类的构造方法是:
    public Hero(){
    }
    这种无参的构造方法,如果不写就会默认提供一个。
    一旦提供了一个有参的构造方法,同时又没有显式的提供一个无参的构造方法,那么默认的无参的构造方法就没了,这是实例化的时候就要带上参数。
    和普通方法一样,构造方法也可以重载。

  2. this
    4.1
    this代表的是当前对象

    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();
    

    }
    在这里插入图片描述
    4.2
    通过this访问属性

//通过this访问属性
    public void setName3(String name){
        //name代表的是参数name
        //this.name代表的是属性name
        this.name = name;
    }

4.3
如果要在一个构造方法中,调用另一个构造方法,可以使用this()

   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);    
   }
}
  1. 如果变量是基本类型,=表赋值;
    如果变量是类类型,=表示指向。
    **在方法内,无法修改方法外的基本类型参数 **
    类类型传参会改变变量值,因为他们指向的是同一个对象
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);//调用attack时,使hero引用指向garen引用。
      System.out.println(teemo.hp);
  }

}

在方法中,使参数引用指向一个新的对象,在,外面的引用指向的是原来的对象,不发生变化。(局部变量无法影响全局变量)


  1. 把比较接近的类,规划在同一个包下。
    使用同一个包下的其他类,可以直接引用;但使用其他包下的类,必须import
package charactor;
 
//Weapon类在其他包里,使用必须进行import
import property.Weapon;
 
public class Hero {
        
    String name; //姓名
        
    float hp; //血量
        
    float armor; //护甲
        
    int moveSpeed; //移动速度
     
    //装备一把武器
    public void equip(Weapon w){
         
    }
        
}
  1. 访问修饰符
    成员变量有四种修饰符
    private 私有的
    package/friendly/default ( 没有修饰符即代表package/friendly/default)
    protected 受保护的
    public 公共的

自身:指的是Hero自己
同包子类:ADHero这个类是Hero的子类,并且和Hero处于同一个包下
不同包子类:Support这个类是Hero的子类,但是在另一个包下
同包类: GiantDragon 这个类和Hero是同一个包,但是彼此没有继承关系
其他类:Item这个类,在不同包,也没有继承关系的类
在这里插入图片描述
7.1 使用private修饰属性
自身:是可以访问的
同包子类:不能继承
不同包子类:不能继承
同包类:不能访问
其他包类:不能访问

7.2 没有修饰符
自己可以访问
同包子类可以继承
不同包子类不能继承
同包类可以访问
不同包类不能访问

7.3 protected饰符的属性 hp
自己可以访问
同包子类可以继承
不同包子类可以继承
同包类可以访问
不同包类不能访问

7.4 public 公共的
任何地方,都可以访问
红字表示不可以继承、访问
红字表示不可以继承、访问

  1. 属性通常使用private封装起来

  2. 方法一般使用public用于被调用

  3. 会被子类继承的方法,通常使用protected

  4. package用的不多,一般新手会用package,因为还不知道有修饰符这个东西

  5. 遵守作用范围最小原则,能用private就用private,不行就放大一级,用package,再不行就用protected,最后用public。

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

访问类属性有两种方式

  1. 对象.类属性
    teemo.copyright
  2. 类.类属性
    Hero.copyright、、建议第二种

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

  1. 类方法
    类方法: 又叫做静态方法
    对象方法: 又叫实例方法,非静态方法
    访问一个对象方法,必须建立在有一个对象的前提的基础上;访问类方法,不需要对象的存在,直接就访问。
    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();
     
}

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

  1. 对象.类方法
    garen.battleWin();
  2. 类.类方法
    Hero.battleWin();//建议第二种

如果一个方法,没有调用任何对象属性,那么就可以考虑设计为类方法; 如果方法里访问了对象属性,那么这个方法,就必须设计为对象方法。

  1. 属性初始化
    对象属性初始化:

    1. 声明该属性的时候初始化
    2. 构造方法中初始化
    3. 初始化块:
      {
      maxHP = 200; //初始化块
      }
      类属性初始化有2种:
  2. 声明该属性的时候初始化

  3. 静态初始化块
    static{
    itemCapacity = 6;//静态初始化块 初始化
    }
    quiz:对象属性的初始化这三种方式,谁先执行?谁后执行?
    ans: 当对一个对象实例化时,首先会加载实例变量,然后再执行初始化代码块,最后执行构造方法。

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

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

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

package charactor;
 
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;
    }
      
}
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);
    }
}

饿汉式是立即加载的方式,无论是否会用到这个对象,都会加载。如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候感觉稍微有些卡顿。
懒汉式,是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量(鉴于同学们学习的进度,暂时不对线程的章节做展开)。使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。
看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式。

  1. 枚举变量
    枚举enum是一种特殊的类(还是类),使用枚举可以很方便的定义常量
public enum Season {
	SPRING,SUMMER,AUTUMN,WINTER
}

swtich语句中常用,可以限定死枚举的范围。

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

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

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

接口与继承

一个类可以有多个子类,一个子类只能有一个父类

  1. 接口
    创建一个接口
    File->New->Interface
package charactor;
public interface AD {
        //物理伤害
    public void physicAttack();
}

实现某个接口,就相当于承诺了某种约定。所以,实现了AD这个接口,就必须提供AD接口中声明的方法physicAttack(),实现在语法上使用关键字 implements。

package charactor;
//同时能进行物理和魔法伤害的英雄
public class ADAPHero extends Hero implements AD,AP{//实现了两个接口
    @Override
    public void magicAttack() {
        System.out.println("进行魔法攻击");
    }
    @Override
    public void physicAttack() {
        System.out.println("进行物理攻击");
    }
}

快捷方式:Ctrl+1

  1. 对象转型
package charactor;
public class Hero {
    public String name;
    protected float hp;    
    public static void main(String[] args) {         
        ADHero ad = new ADHero();
    }
}

在这个例子里,有一个对象 new ADHero(), 同时也有一个引用ad
对象是有类型的, 是ADHero
引用也是有类型的,是ADHero
通常情况下,引用类型和对象类型是一样的。

2.1 转型
所谓的转型,是指当引用类型和对象类型不一致的时候,才需要进行类型转换。把右边的当做左边来用,看说得通不,如果说得通就转型成功。
2.1.1子类转父类

Hero h = new Hero();
ADHero ad = new ADHero();
h = ad;

右边ad引用所指向的对象的类型是 物理攻击英雄
左边h引用的类型是 普通英雄
把物理攻击英雄 当做 普通英雄,说不说得通? 说得通,就可以转。
所有的子类转换为父类,都是说得通的。
2.1.2 父类转子类
父类转子类,有的时候行,有的时候不行,所以必须进行强制转换。强制转换的意思就是 转换有风险,风险自担。

package charactor;
import charactor1.Support;  
public class Hero {
    public String name;
    protected float hp;      
    public static void main(String[] args) {
        Hero h =new Hero();
        ADHero ad = new ADHero();
        Support s =new Support();
        h = ad;
        ad = (ADHero) h;
        h = s;
        ad = (ADHero)h;
    }
}

14行: 把ad当做Hero使用,一定可以
转换之后,h引用指向一个ad对象
15行: h引用有可能指向一个ad对象,也有可能指向一个support对象。所以把h引用转换成AD类型的时候,就有可能成功,有可能失败。因此要进行强制转换,换句话说转换后果自负。到底能不能转换成功,要看引用h到底指向的是哪种对象。在这个例子里,h指向的是一个ad对象,所以转换成ADHero类型,是可以的。
16行:把一个support对象当做Hero使用,一定可以。转换之后,h引用指向一个support对象。
17行:这个时候,h指向的是一个support对象,所以转换成ADHero类型,会失败。失败的表现形式是抛出异常ClassCastException,类型转换异常
在这里插入图片描述
2.1.3
没有继承关系的两个类,互相转换,一定会失败,虽然ADHero和APHero都继承了Hero,但是彼此没有互相继承关系,转换会失败。

2.1.4 实现类转换成接口(向上转型)

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

引用ad指向的对象是ADHero类型,这个类型实现了AD接口
10行: 把一个ADHero类型转换为AD接口
从语义上来讲,把一个ADHero当做AD来使用,而AD接口只有一个physicAttack方法,这就意味着转换后就有可能要调用physicAttack方法,而ADHero一定是有physicAttack方法的,所以转换是能成功的。

2.1.5 接口转化成实现类(向下转型)

package charactor;  
public class Hero {
    public String name;
    protected float hp;    
    public static void main(String[] args) {
        ADHero ad = new ADHero();            
        AD adi = ad;   
        ADHero adHero = (ADHero) adi;            
        ADAPHero adapHero = (ADAPHero) adi;
        adapHero.magicAttack();
    }       
}

10行: ad引用指向ADHero, 而adi引用是接口类型:AD,实现类转换为接口,是向上转型,所以无需强制转换,并且一定能成功
12行: adi实际上是指向一个ADHero的,所以能够转换成功
14行: adi引用所指向的对象是一个ADHero,要转换为ADAPHero就会失败。
假设能够转换成功,那么就可以使用magicAttack方法,而adi引用所指向的对象ADHero是没有magicAttack方法的。
在这里插入图片描述

package charactor;
public class Hero {
    public String name;
    protected float hp;      
    public static void main(String[] args) {
        ADHero ad = new ADHero();
        APHero ap = new APHero();        
        Hero h1= ad;
        Hero h2= ap;         
        //判断引用h1指向的对象,是否是ADHero类型
        System.out.println(h1 instanceof ADHero);        
        //判断引用h2指向的对象,是否是APHero类型
        System.out.println(h2 instanceof APHero);     
        //判断引用h1指向的对象,是否是Hero的子类型
        System.out.println(h1 instanceof Hero);
    }
}

instanceof Hero 判断一个引用所指向的对象,是否是Hero类型,或者Hero的子类。

  1. 重写 //override
    从父类继承了方法以后,有些方法想要其他效果,就再写一次,调用的时候会执行子类的方法,这就叫重写。
package property;
public class Item {   //父类
    String name;
    int price; 
    public void buy(){
        System.out.println("购买");
    }
    public void effect() {
        System.out.println("物品使用后,可以有效果");
    } 
}
package property; 
public class LifePotion extends Item{     //子类
    public void effect(){
        System.out.println("血瓶使用后,可以回血");
    }     
    public static void main(String[] args) {
    	LifePotion lp =new LifePotion();
        lp.effect();
     }
}
  1. 多态
    4.1 操作符的多态
    如果+号两侧都是整型,那么+代表 数字相加。
    如果+号两侧,任意一个是字符串,那么+代表字符串连接。
    4.2 类的多态
    都是同一个类型,调用同一个方法,却能呈现不同的状态。
package property; 
public class Item {
    String name;
    int price; 
    public void buy(){
        System.out.println("购买");
    }
    public void effect() {
        System.out.println("物品使用后,可以有效果 ");
    }   
    public static void main(String[] args) {
        Item i1= new LifePotion();
        Item i2 = new MagicPotion();
        System.out.print("i1  是Item类型,执行effect打印:");
        i1.effect();
        System.out.print("i2也是Item类型,执行effect打印:");
        i2.effect();
    } 
}

要实现类的多态,需要如下条件
1.父类(接口)引用指向子类对象
2.调用的方法有重写

使用多态可以通过重写来减少方法。

  1. 类方法
    与重写类似,方法的重写是子类覆盖父类的对象方法。隐藏,就是子类覆盖父类的类方法
package charactor; 
public class Hero {
    public String name;
    protected float hp;  
    //类方法,静态方法
    //通过类就可以直接调用
    public static void battleWin(){
        System.out.println("hero battle win");
    }      
}
package charactor;  
public class ADHero extends Hero implements AD{  
    @Override
    public void physicAttack() {
        System.out.println("进行物理攻击");
    }     
    //隐藏父类的battleWin方法
    public static void battleWin(){
        System.out.println("ad hero battle win");
    }        
    public static void main(String[] args) {
        Hero.battleWin();//调用父类的类方法
        ADHero.battleWin();//调用子类的类方法
    }  
}
  1. super关键字
    6.1 在实例化Hero对象的时候,会调用构造方法。
    6.2 在实例化子类的对象的时候,会调用父类的构造方法和子类的构造方法,并且父类的构造方法先调用。
    6.3 如果父类显示提供两个构造方法,有参和无参
package charactor; 
import property.Item; 
public class Hero {       
    String name; //姓名      
    float hp; //血量        
    float armor; //护甲        
    int moveSpeed; //移动速度     
    public void useItem(Item i){
        System.out.println("hero use item");
        i.effect();
    }        
    public Hero(){
        System.out.println("Hero的无参的构造方法 ");
    }     
    public Hero(String name){
        System.out.println("Hero的有一个参数的构造方法 ");
        this.name = name;
    }     
    public static void main(String[] args) {
        new Hero();
    }      
}

会默认调用无参的构造函数。即使是实例化对象的时候带了参数,也会默认调用无参的构造函数。
6.4 super关键字的作用
1、super表示超(父)类的意思,this表示对象本身。
2、super可用于访问父类被子类隐藏或着覆盖的方法和属性,使用形式为super.方法(属性。
3、在类的继承中,子类的构造方法中默认会有super()语句存在(默认隐藏),相当于执行父类的相应构造方法中的语句,若显式使用则必须位于类的第一行 。
4、对于父类有参的构造方法,super不能省略,否则无法访问父类的有参构造方法,使用形式为super(xx,xx…)。

class Person {  
       protected void print() {  
          System.out.println("The print() in class Person.");  
       }  
   }         
   public class DemoSuper extends Person {        
       public DemoSuper(){        
          super(); //调用父类的构造方法,而且放第一行,如果不写,系统自动加  
       }  
       public void print() {  
          System.out.println("The print() in class DemoSuper.");  
          super.print();// 调用父类的方法  
       }         
       public static void main(String[] args) {  
          DemoSuper ds = new DemoSuper();  
          ds.print();  
       }  
   }
  1. object类
    6.1 object类是所有类的父类
    声明一个类的时候,默认是继承了Object
    public class Hero extends Object
    6.2 Object类提供一个toString方法,所以所有的类都有toString方法。toString()的意思是返回当前对象的字符串表达。通过 System.out.println 打印对象就是打印该对象的toString()返回值
package charactor;  
public class Hero {
    public String name;
    protected float hp;      
    public String toString(){
        return name;
    }      
    public static void main(String[] args) {        
        Hero h = new Hero();
        h.name = "盖伦";
        System.out.println(h.toString());
        //直接打印对象就是打印该对象的toString()返回值
        System.out.println(h);
    }
}

6.3 finalize()//垃圾回收
当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件
当它被垃圾回收的时候,它的finalize() 方法就会被调用。
finalize() 不是开发人员主动调用的方法,而是由虚拟机JVM调用的。

package charactor;  
public class Hero {
    public String name;
    protected float hp;      
    public String toString(){
        return name;
    }     
    public void finalize(){
        System.out.println("这个英雄正在被回收");
    }      
    public static void main(String[] args) {
        //只有一引用
        Hero h;
        for (int i = 0; i < 100000; i++) {
            //不断生成新的对象
            //每创建一个对象,前一个对象,就没有引用指向了
            //那些对象,就满足垃圾回收的条件
            //当,垃圾堆积的比较多的时候,就会触发垃圾回收
            //一旦这个对象被回收,它的finalize()方法就会被调用
            h = new Hero();
        } 
    }
}

6.4 equals()和 ==
equals() 用于判断两个对象的内容是否相同
1、“==”比较两个变量本身的值,即两个对象在内存中的首地址,通俗的讲,用于判断两个引用是否指向同一个对象。
2、“equals()”比较字符串中所包含的内容是否相同。

String s1,s2,s3 = "abc", s4 ="abc" ;
s1 = new String("abc");
s2 = new String("abc");
s1==s2   是 false      //两个变量的内存地址不一样,也就是说它们指向的对象不 一样,
s1.equals(s2)true    //两个变量的所包含的内容是abc,故相等。

6.5 hashCode()
hashCode方法返回一个对象的哈希值
6.6线程同步相关方法
wait()
notify()
notifyAll()
6.6 getClass()
getClass()会返回一个对象的类对象

  1. final
    当类被修饰成final时,表示类不能够被继承,其子类会出现编译错误。
    7.1 final修饰类
package charactor; 
public final class Hero extends Object {        
    String name; //姓名        
    float hp; //血量        
}

7.2 final修饰方法
Hero的useItem方法被修饰成final,那么该方法在ADHero中,不能够被重写

package charactor; 
import property.Item; 
public class Hero extends Object {        
    String name; //姓名        
    float hp; //血量        
    float armor; //护甲        
    int moveSpeed; //移动速度     
    public final void useItem(Item i){
        System.out.println("hero use item");
        i.effect();
    }     
    public Hero(){
        System.out.println("Hero的无参的构造方法 ");
    }     
    public Hero(String name){
        System.out.println("Hero的有一个参数的构造方法 ");
        this.name = name;
    }     
    public static void main(String[] args) {
        new Hero();
    }      
}

7.3 final修饰基本类型变量

package charactor; 
public class Hero extends Object {        
    String name; //姓名        
    float hp; //血量        
    float armor; //护甲        
    int moveSpeed; //移动速度   
    public static void main(String[] args) {
        final int hp;
        hp = 5;
        hp = 6;         
    }
}

7.4 final修饰引用
final修饰引用
h引用被修饰成final,表示该引用只有1次指向对象的机会。

final Hero h;
h  =new Hero();
h  =new Hero();//编译出错

7.5 final定义常量
常量指的是可以公开,直接访问,不会变化的值 .

  public static final int itemTotalNumber = 6;//物品栏的数量

String 类有final修饰,不能被继承。

  1. 抽象类
    在类中声明一个方法,这个方法没有实现体,是一个“空”方法
    这样的方法就叫抽象方法,使用修饰符“abstract”
    当一个类有抽象方法的时候,该类必须被声明为抽象类
package charactor; 
public abstract class Hero {
    String name; 
    float hp; 
    float armor; 
    int moveSpeed; 
    public static void main(String[] args) { 
    } 
    // 抽象方法attack
    // Hero的子类会被要求实现attack方法
    public abstract void attack(); 
}

为Hero增加一个抽象方法 attack,并且把Hero声明为abstract的。
APHero,ADHero,ADAPHero是Hero的子类,继承了Hero的属性和方法。
但是各自的攻击手段是不一样的,所以继承Hero类后,这些子类就必须提供不一样的attack方法实现。
8.1 抽象类可以没有抽象方法
Hero类可以在不提供抽象方法的前提下,声明为抽象类。
一旦一个类被声明为抽象类,就不能够被直接实例化 。

package charactor;   
public abstract class Hero {
    String name;          
    float hp;          
    float armor;          
    int moveSpeed;       
    public static void main(String[] args) {
        //虽然没有抽象方法,但是一旦被声明为了抽象类,就不能够直接被实例化
        Hero h= new Hero();//提示错误
    }          
}

8.2 抽象类和接口的区别
1、子类只能继承一个抽象类,不能继承多个;子类可以实现多个接口。
2、
抽象类可以定义
public,protected,package,private
静态和非静态属性
final和非final属性
但是接口中声明的属性,只能是
public static final的
即便没有显式的声明

抽象类和接口都可以有实体方法。 接口中的实体方法,叫做默认方法

  1. 内部类
    内部类分为四种:
    非静态内部类
    静态内部类
    匿名类
    本地类
    9.1 非静态内部类
    非静态内部类可以直接在一个类里面定义。
    战斗成绩只有在一个英雄对象存在的时候才有意义
    所以实例化BattleScore 的时候,必须建立在一个存在的英雄的基础上
    语法: new 外部类().new 内部类()
    作为Hero的非静态内部类,是可以直接访问外部类的private实例属性name的
package charactor;
 
public class Hero {
    private String name; // 姓名
 
    float hp; // 血量
 
    float armor; // 护甲
 
    int moveSpeed; // 移动速度
 
    // 非静态内部类,只有一个外部类对象存在的时候,才有意义
    // 战斗成绩只有在一个英雄对象存在的时候才有意义
    class BattleScore {
        int kill;
        int die;
        int assit;
 
        public void legendary() {
            if (kill >= 8)
                System.out.println(name + "超神!");
            else
                System.out.println(name + "尚未超神!");
        }
    }
 
    public static void main(String[] args) {
        Hero garen = new Hero();
        garen.name = "盖伦";
        // 实例化内部类
        // BattleScore对象只有在一个英雄对象存在的时候才有意义
        // 所以其实例化必须建立在一个外部类对象的基础之上
        BattleScore score = garen.new BattleScore();
        score.kill = 9;
        score.legendary();
    }
 
}

9.2 静态内部类
在一个类里面声明一个静态内部类
比如敌方水晶,当敌方水晶没有血的时候,己方所有英雄都取得胜利,而不只是某一个具体的英雄取得胜利。
与非静态内部类不同,静态内部类水晶类的实例化不需要一个外部类的实例为基础,可以直接实例化
语法:new 外部类.静态内部类();
因为没有一个外部类的实例,所以在静态内部类里面不可以访问外部类的实例属性和方法
除了可以访问外部类的私有静态成员外,静态内部类和普通类没什么大的区别

static class EnemyCrystal{
        int hp=5000;
 }
  public static void main(String[] args) {
        //实例化静态内部类
        Hero.EnemyCrystal crystal = new Hero.EnemyCrystal();       

9.3 匿名类
匿名类指的是在声明一个类的同时实例化它,使代码更加简洁精练
通常情况下,要使用一个接口或者抽象类,都必须创建一个子类
有的时候,为了快速使用,直接实例化一个抽象类,并“当场”实现其抽象方法。
既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。

package charactor;
   
public abstract class Hero {
    String name; //姓名
          
    float hp; //血量
          
    float armor; //护甲
          
    int moveSpeed; //移动速度
      
    public abstract void attack();
      
    public static void main(String[] args) {
          
        ADHero adh=new ADHero();
        //通过打印adh,可以看到adh这个对象属于ADHero类
        adh.attack();
        System.out.println(adh);
          
        Hero h = new Hero(){
            //当场实现attack方法
            public void attack() {
                System.out.println("新的进攻手段");
            }
        };//注意这个分号
        h.attack();
        //通过打印h,可以看到h这个对象属于Hero$1这么一个系统自动分配的类名
          
        System.out.println(h);
    }
      
}

9.4 本地方法
本地类可以理解为有名字的匿名类
内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置。
本地类和匿名类一样,直接声明在代码块里面,可以是主方法,for循环里等等地方

package charactor;
   
public abstract class Hero {
    String name; //姓名
          
    float hp; //血量
          
    float armor; //护甲
          
    int moveSpeed; //移动速度
      
    public abstract void attack();
      
    public static void main(String[] args) {
          
        //与匿名类的区别在于,本地类有了自定义的类名
        class SomeHero extends Hero{
            public void attack() {
                System.out.println( name+ " 新的进攻手段");
            }
        }
         
        SomeHero h  =new SomeHero();
        h.name ="地卜师";
        h.attack();
    }
      
}

9.5 在匿名类中使用外部的局部变量
在匿名类中使用外部的局部变量,外部的局部变量必须修饰为final。

  1. 默认方法
    默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法
    Mortal 这个接口,增加了一个默认方法 == revive,这个方法有实现体,并且被声明为了default==
package charactor;
 
public interface Mortal {
    public void die();
 
    default public void revive() {
        System.out.println("本英雄复活了");
    }
}

假设没有默认方法这种机制,那么如果要为Mortal增加一个新的方法revive,那么所有实现了Mortal接口的类,都需要做改动。
但是引入了默认方法后,原来的类,不需要做任何改动,并且还能得到这个默认方法
通过这种手段,就能够很好的扩展新的类,并且做到不影响原来的类 //降低开发和维护效率

为AD接口增加一个默认方法 attack()
为AP接口也增加一个默认方法 attack()
问: ADAPHero同时实现了AD,AP接口,那么 ADAPHero 对象调用attack()的时候,是调用哪个接口的attack()?
ans:使用AD.super.attack(),即可调用默认的attack()

  1. UML图
    UML-Unified Module Language
    统一建模语言,可以很方便的用于描述类的属性,方法,以及类和类之间的关系
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    带箭头的实线,表示 Spider,Cat, Fish都继承于Animal这个父类.
    注: 模糊是表示,此时不需要关注模糊的那部分内容。
    在这里插入图片描述
    表示 Fish实现了 Pet这个接口。

数字与字符串

  1. 装箱与拆箱
    1.1 封装类
    所有的基本类型,都有对应的类类型
    比如int对应的类是Integer
    这种类就叫做封装类
    1.2 Number类
    数字封装类有
    Byte,Short,Integer,Long,Float,Double
    这些类都是抽象类Number的子类
    在这里插入图片描述
    1.3 封装类与基本类互转
package digit; 
public class TestNumber { 
    public static void main(String[] args) {
        int i = 5; 
        //基本类型转换成封装类型
        Integer it = new Integer(i);        
        //封装类型转换成基本类型
        int i2 = it.intValue();  
    }
}

1.4 自动装箱
不需要调用构造方法,通过=符号自动把 基本类型 转换为 类类型 就叫装箱

package digit;
 
public class TestNumber {
 
    public static void main(String[] args) {
        int i = 5;
 
        //基本类型转换成封装类型
        Integer it = new Integer(i);
         
        //自动转换就叫装箱
        Integer it2 = i;
         
    }
}

1.5 自动拆箱
不需要调用Integer的intValue方法,通过=就自动转换成int类型,就叫拆箱

package digit;
  
public class TestNumber {
  
    public static void main(String[] args) {
        int i = 5;
  
        Integer it = new Integer(i);
          
        //封装类型转换成基本类型
        int i2 = it.intValue();
         
        //自动转换就叫拆箱
        int i3 = it;
          
    }
}

1.6 int的最大值,最小值
int的最大值可以通过其对应的封装类Integer.MAX_VALUE获取

package digit;
  
public class TestNumber {
  
    public static void main(String[] args) {
 
        //int的最大值
        System.out.println(Integer.MAX_VALUE);
        //int的最小值      
        System.out.println(Integer.MIN_VALUE);
          
    }
}
  1. 字符串转换
    2.1数字转字符串
    方法1: 使用String类的静态方法valueOf
    方法2: 先把基本类型装箱为对象,然后调用对象的toString
package digit;
  
public class TestNumber {
  
    public static void main(String[] args) {
        int i = 5;
         
        //方法1
        String str = String.valueOf(i);
         
        //方法2
        Integer it = i;
        String str2 = it.toString();
         
    }
}

2.2 字符串转数字
调用Integer的静态方法parseInt

package digit;
  
public class TestNumber {
  
    public static void main(String[] args) {
 
        String str = "999";
         
        int i= Integer.parseInt(str);
         
        System.out.println(i);
         
    }
}
  1. 数学方法
    3.1 四舍五入, 随机数,开方,次方,π,自然常数
package digit;
  
public class TestNumber {
  
    public static void main(String[] args) {
        float f1 = 5.4f;
        float f2 = 5.5f;
        //5.4四舍五入即5
        System.out.println(Math.round(f1));
        //5.5四舍五入即6
        System.out.println(Math.round(f2));
         
        //得到一个0-1之间的随机浮点数(取不到1)
        System.out.println(Math.random());
         
        //得到一个0-10之间的随机整数 (取不到10)
        System.out.println((int)( Math.random()*10));
        //开方
        System.out.println(Math.sqrt(9));
        //次方(2的4次方)
        System.out.println(Math.pow(2,4));
         
        //π
        System.out.println(Math.PI);
         
        //自然常数
        System.out.println(Math.E);
    }
}
  1. 格式化输出
    如果不使用格式化输出,就需要进行字符串连接,如果变量比较多,拼接就会显得繁琐
    使用格式化输出,就可以简洁明了
    %s 表示字符串
    %d 表示数字
    %n 表示换行
package digit;
  
public class TestNumber {
  
    public static void main(String[] args) {
 
        String name ="盖伦";
        int kill = 8;
        String title="超神";
         
        //直接使用+进行字符串连接,编码感觉会比较繁琐,并且维护性差,易读性差
        String sentence = name+ " 在进行了连续 " + kill + " 次击杀后,获得了 " + title +" 的称号";
         
        System.out.println(sentence);
         
        //使用格式化输出
        //%s表示字符串,%d表示数字,%n表示换行
        String sentenceFormat ="%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n";
        System.out.printf(sentenceFormat,name,kill,title);//format能够达到一模一样的效果
         
    }
}

4.1 换行符
(1)在DOS和Windows中,每行结尾是 “\r\n”;
(2)Linux系统里,每行结尾只有 “\n”;
(3)Mac系统里,每行结尾是只有 “\r”。
为了使得同一个java程序的换行符在所有的操作系统中都有一样的表现,使用%n,就可以做到平台无关的换行

4.2 总长度,左对齐,补0,千位分隔符,小数点位数,本地化表达

package digit;
  
import java.util.Locale;
   
public class TestNumber {
   
    public static void main(String[] args) {
        int year = 2020;
        //总长度,左对齐,补0,千位分隔符,小数点位数,本地化表达
          
        //直接打印数字
        System.out.format("%d%n",year);
        //总长度是8,默认右对齐
        System.out.format("%8d%n",year);
        //总长度是8,左对齐
        System.out.format("%-8d%n",year);
        //总长度是8,不够补0
        System.out.format("%08d%n",year);
        //千位分隔符
        System.out.format("%,8d%n",year*10000);
  
        //小数点位数
        System.out.format("%.2f%n",Math.PI);
          
        //不同国家的千位分隔符
        System.out.format(Locale.FRANCE,"%,.2f%n",Math.PI*10000);
        System.out.format(Locale.US,"%,.2f%n",Math.PI*10000);
        System.out.format(Locale.UK,"%,.2f%n",Math.PI*10000);
          
    }
}

在这里插入图片描述
5. 字符
5.1 保留一个字符时用char
5.2 char对应的封装类是Character
Character c = c1;//自动装箱
c1 = c;//自动拆箱
5.3 Character的常见方法

package character;
 
public class TestChar {
 
    public static void main(String[] args) {
         
        System.out.println(Character.isLetter('a'));//判断是否为字母
        System.out.println(Character.isDigit('a')); //判断是否为数字
        System.out.println(Character.isWhitespace(' ')); //是否是空白
        System.out.println(Character.isUpperCase('a')); //是否是大写
        System.out.println(Character.isLowerCase('a')); //是否是小写
         
        System.out.println(Character.toUpperCase('a')); //转换为大写
        System.out.println(Character.toLowerCase('A')); //转换为小写
 
        String a = 'a'; //不能够直接把一个字符转换成字符串
        String a2 = Character.toString('a'); //转换为字符串
         
    }
}

5.4常见歧义

package character;
  
public class TestChar {
  
    public static void main(String[] args) {
        System.out.println("使用空格无法达到对齐的效果");
        System.out.println("abc def");
        System.out.println("ab def");
        System.out.println("a def");
          
        System.out.println("使用\\t制表符可以达到对齐的效果");
        System.out.println("abc\tdef");
        System.out.println("ab\tdef");
        System.out.println("a\tdef");
         
        System.out.println("一个\\t制表符长度是8");
        System.out.println("12345678def");
          
        System.out.println("换行符 \\n");
        System.out.println("abc\ndef");
 
        System.out.println("单引号 \\'");
        System.out.println("abc\'def");
        System.out.println("双引号 \\\"");
        System.out.println("abc\"def");
        System.out.println("反斜杠本身 \\");
        System.out.println("abc\\def");
    }
}
  1. 字符串
    6.1 创建字符串
    常见创建字符串手段:
    1、 每当有一个字面值出现的时候,虚拟机就会创建一个字符串
    2、调用String的构造方法创建一个字符串对象
    3.、 通过+加号进行字符串拼接也会创建新的字符串对象
   String garen ="盖伦"; //字面值,虚拟机碰到字面值就会创建一个字符串对象
   
     String hero = new String(cs);//  通过字符数组创建一个字符串对象
         
        String hero3 = garen + teemo;//  通过+加号进行字符串拼接

6.2 String 被修饰为final,所以是不能被继承的

6.3 immutable
immutable 是指不可改变的
比如创建了一个字符串对象
String garen =“盖伦”;
不可改变的具体含义是指:
不能增加长度
不能减少长度
不能插入字符
不能删除字符
不能修改字符
一旦创建好这个字符串,里面的内容 永远 不能改变
String 的表现就像是一个常量

6.4 字符串长度
length方法可以返回当前字符串的长度
可以有长度为0的字符串,即空字符串

6.5 字符串格式化输出
String类也有format方法,可以得到格式化后的字符串。

6.6
创建一个长度是5的随机字符串的方法

        String pool = "";
        for (short i = '0'; i <= '9'; i++) {
            pool+=(char)i;
        }
        for (short i = 'a'; i <= 'z'; i++) {
            pool+=(char)i;
        }
        for (short i = 'A'; i <= 'Z'; i++) {
            pool+=(char)i;
        }
        char cs2[] = new char[5];
        for (int i = 0; i < cs2.length; i++) {
            int index = (int) (Math.random()*pool.length());
            cs2[i] =  pool.charAt( index );
        }
        String result2 = new String(cs2);
        System.out.println(result2);
  1. 操作字符串
    7.1 charAt(int index)获取指定位置的字符
package character;    
public class TestString {    
    public static void main(String[] args) {   
        String sentence = "盖伦,在进行了连续8次击杀后,获得了 超神 的称号";         
        char c = sentence.charAt(0);         
        System.out.println(c);        
    }
}

7.2 toCharArray(),获取对应的字符数组
7.3 subString,截取子字符串

package character;    
public class TestString {    
    public static void main(String[] args) { 
        String sentence = "盖伦,在进行了连续8次击杀后,获得了 超神 的称号";         
        //截取从第3个开始的字符串 (基0)
        String subString1 = sentence.substring(3);        
        System.out.println(subString1);         
        //截取从第3个开始的字符串 (基0)
        //到5-1的位置的字符串
        //左闭右开
        String subString2 = sentence.substring(3,5);         
        System.out.println(subString2);         
    }
}

7.4 split,根据分隔符进行分隔

package character;    
public class TestString {    
    public static void main(String[] args) {   
        String sentence = "盖伦,在进行了连续8次击杀后,获得了 超神 的称号";         
        //根据,进行分割,得到3个子字符串
        String subSentences[] = sentence.split(",");
        for (String sub : subSentences) {            System.out.println(sub);
        }           
    }
}

7.5 trim去掉首位空格

package character;    
public class TestString {   
    public static void main(String[] args) {   
        String sentence = "        盖伦,在进行了连续8次击杀后,获得了 超神 的称号      ";         
        System.out.println(sentence);
        //去掉首尾空格        System.out.println(sentence.trim());
    }
}

7.6
toLowerCase 全部变成小写
toUpperCase 全部变成大写

7.7 定位
indexOf 判断字符或者子字符串出现的位置
contains 是否包含子字符串

package character;     
public class TestString {    
    public static void main(String[] args) {    
        String sentence = "盖伦,在进行了连续8次击杀后,获得了超神 的称号";
         System.out.println(sentence.indexOf('8')); //字符第一次出现的位置
                 System.out.println(sentence.indexOf("超神")); //字符串第一次出现的位置
                  System.out.println(sentence.lastIndexOf("了")); //字符串最后出现的位置
                 System.out.println(sentence.indexOf(',',5)); //从位置5开始,出现的第一次,的位置
                          System.out.println(sentence.contains("击杀")); //是否包含字符串"击杀"         
    }
}

7.8 替换
replaceAll 替换所有的
replaceFirst 只替换第一个

package character;    
public class TestString {    
    public static void main(String[] args) {   
        String sentence = "盖伦,在进行了连续8次击杀后,获得了超神 的称号"; 
        String temp = sentence.replaceAll("击杀", "被击杀"); //替换所有的        
        temp = temp.replaceAll("超神", "超鬼");         
        System.out.println(temp);         
        temp = sentence.replaceFirst(",","");//只替换第一个         
        System.out.println(temp);         
    }
}
  1. 比较字符串
    1、equal方法 //内容比较
    2、== //对象比较
    一般说来,编译器每碰到一个字符串的字面值,就会创建一个新的对象
    所以在第6行会创建了一个新的字符串"the light"
    但是在第7行,编译器发现已经存在现成的"the light",那么就直接拿来使用,而没有进行重复创建
package character; 
public class TestString { 
    public static void main(String[] args) {
        String str1 = "the light";
        String str3 = "the light";
        System.out.println( str1  ==  str3);
    } 
}

8.1
startsWith //以…开始
endsWith //以…结束

package character; 
public class TestString {  
    public static void main(String[] args) {
        String str1 = "the light";         
        String start = "the";
        String end = "Ight";                 System.out.println(str1.startsWith(start));//以...开始        System.out.println(str1.endsWith(end));//以...结束          
    }  
}
  1. StringBuffer
    9.1 追加 删除 插入 反转
    append追加
    delete 删除
    insert 插入
    reverse 反转 //首尾

9.2 长度 容量
为什么StringBuffer可以变长?
和String内部是一个字符数组一样,StringBuffer也维护了一个字符数组。 但是,这个字符数组,留有冗余长度
比如说new StringBuffer(“the”),其内部的字符数组的长度,是19,而不是3,这样调用插入和追加,在现成的数组的基础上就可以完成了。
如果追加的长度超过了19,就会分配一个新的数组,长度比原来多一些,把原来的数据复制到新的数组中

package character;  
public class TestString {
      public static void main(String[] args) {
        String str1 = "the"; 
        StringBuffer sb = new StringBuffer(str1);
                 System.out.println(sb.length()); //内容长度
                 System.out.println(sb.capacity());//总空间  
    }  
}

length: “the”的长度 3
capacity: 分配的总空间 19
注: 19这个数量,不同的JDK数量是不一样的
StringBuffer 的运行效率比String高

Java饮料自动贩卖机可以使用简单工厂模式来实现。简单工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在简单工厂模式中,我们创建对象而不是通过直接实例化类来完成的。这样可以将对象的创建与使用分离,从而提高代码的可维护性和可扩展性。 具体实现步骤如下: 1. 定义一个饮料抽象类Drink,包含两个抽象方法sell和comein。 2. 定义具体饮料类,如Coffee、Tea等,继承Drink类并实现其抽象方法。 3. 定义一个饮料工厂类DrinkFactory,包含一个静态方法createDrink,根据传入的参数创建相应的饮料对象。 4. 在主函数中调用DrinkFactory的createDrink方法创建饮料对象,并调用其sell和comein方法实现售卖和进货功能。 以下是一个简单的Java饮料自动贩卖机的代码示例: ```java // 饮料抽象类 public abstract class Drink { public abstract void sell(String name, int num); public abstract void comein(String name, int num); } // 咖啡类 public class Coffee extends Drink { private String Coffeename; private int num;//按升作单位 public Coffee() { Coffeename = "咖啡"; num = 20; } @Override public void sell(String name, int num) { this.num -= num; System.out.println("你的" + num + "ml" + Coffeename + "已出柜"); } @Override public void comein(String name, int num) { this.num += num; System.out.println(Coffeename + "总量为:" + this.num); } } // 饮料工厂类 public class DrinkFactory { public static Drink createDrink(String drinkType) { Drink drink = null; if (drinkType.equalsIgnoreCase("coffee")) { drink = new Coffee(); } else if (drinkType.equalsIgnoreCase("tea")) { drink = new Tea(); } return drink; } } // 主函数 public class Main { public static void main(String[] args) { Drink coffee = DrinkFactory.createDrink("coffee"); coffee.sell("咖啡", 10); coffee.comein("咖啡", 5); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值