1、StringBuilder类

在 Java 中,我们可以使用 + 来拼接字符串,类似于下面的代码:

String s = "";
for (int i = 0; i < 1000; i++) {
    s = s + "," + i;
}

但是在每次循环中都会创建新的字符串对象(因为字符串是不可变的),然后扔掉旧的字符串。这样,绝大部分字符串都是临时对象,不但浪费内存,还会影响GC效率。

为了能高效拼接字符串,Java标准库提供了StringBuilder,它是一个可变对象,可以预分配缓冲区,这样,往StringBuilder中新增字符时,不会创建新的临时对象:

StringBuilder sb = new StringBuilder(1024);
for (int i = 0; i < 1000; i++) {
    //StringBuilder可以进行链式操作
    sb.append(',').append(i);
}
String s = sb.toString();

对于一般的字符串操作,我们可以不必将其改写为 StringBuilder,在对字符串进行频繁的插入、删除等操作时可以将其改写成 StringBuilder。

 

2、JavaBean

JavaBean 是一种符合命名规范的 class,也就是说,只要符合这些命名规范的类,都可以称之为 JavaBean。

JavaBean 的命名规范:

  1. JavaBean 类必须是一个公共类,即访问修饰符为 public
  2. JavaBean 类必须有一个空的构造函数,类中必须有一个无参的public构造方法
  3. JavaBean类不应有公共实例变量,类变量都应该是 private
  4. 属性(注意,不是成员变量,属性指的是getter或者setter方法名后面的属性名,比如getName,属性即为name)应该由一组读写方法(getXxx 和 setXxx)来访问,一个 JavaBean 对象的属性可以是可读写、或只读、或只写。可以用IDE (Eclipse、IntelliJ IDEA) 来为属性自动生成 getter / setter 方法。(如果操作的字段为boolean类型,此时的读方法不应该命名为 getter 方法,而是 is 方法,例如把 getName 变成 isName)

比如:

public class Person {
    private String age;
    private boolean man;  

    public String getAge() { return this.age; }
    public void setAge(String age) { this.age= age; }

    public boolean isMan(){};    // 读方法
    public void setMan(boolean value){}  // 写方法

    //属性只需要定义getter和setter方法,不是一定需要有对应的字段即成员变量。比如这个类中就没有下面对应的child字段
    public boolean isChild() {
        return age <= 6;
    }
}

我们通常把一组对应的读方法(getter)和写方法(setter)称为属性,例如,name属性:

  • 对应的读方法是String getName()
  • 对应的写方法是setName(String)

只有getter的属性称为只读属性,只有setter的属性称为只写属性,很明显,只读属性很常见,只写属性不常见。

 

3、枚举类(enum)

我们使用 enum 来定义枚举类。枚举类中的每个枚举都是单例模式,枚举类中的实例对象是有限且固定的。

public class Main {
    public static void main(String[] args) {
        Weekday day = Weekday.SUN;    //创建枚举类中的一个实例对象
        if (day == Weekday.SAT || day == Weekday.SUN) {    //多次创建同一个值的枚举对象,拿到的都是同一个对象
            System.out.println("Work at home!");
        } else {
            System.out.println("Work at office!");
        }
    }
}

enum Weekday {
    SUN, MON, TUE, WED, THU, FRI, SAT;
}

使用enum定义的枚举类是一种引用类型,引用类型比较,要始终使用equals()方法,但enum类型可以例外。这是因为enum类型的每个常量在JVM中只有一个唯一实例,所以可以直接用==比较

 

3.1、枚举类的特点

通过enum定义的枚举类,和其他的class没有任何区别,enum定义的类型就是class,只不过它有以下几个特点:

  • 定义的enum类型总是继承自java.lang.Enum,且无法被继承;
  • 只能定义出enum的实例,而无法通过new操作符创建enum的实例;
  • 定义的每个实例都是引用类型的唯一实例;
  • 可以将enum类型用于switch语句

原理:

//我们定义的Color枚举类:
public enum Color {
    RED, GREEN, BLUE;
}

//编译器编译出的class大概就像这样:
public final class Color extends Enum { // 继承自Enum,标记为final class
    // 每个常量均为全局唯一,并且都是实例
    public static final Color RED = new Color();
    public static final Color GREEN = new Color();
    public static final Color BLUE = new Color();

    // private构造方法,确保外部无法调用new操作符:
    private Color() {}
}

所以,编译后的enum类和普通class并没有任何区别。但是我们自己无法按定义普通class那样来定义enum,必须使用enum关键字,这是Java语法规定的。

 

3.2、枚举值的方法

因为enum是一个class,每个枚举的值都是class实例,因此,这些实例有一些方法,如下:

name()方法 返回常量名

String s = Weekday.SUN.name(); // "SUN"

 

ordinal()返回定义的常量的顺序,从0开始计数

int n = Weekday.MON.ordinal(); // 1

但是改变枚举常量的顺序就会导致ordinal()返回值发生变化。

 

因为enum本身是class,所以我们可以定义private的构造方法,并且,给每个枚举常量添加字段:

public class Main {
    public static void main(String[] args) {
        Weekday day = Weekday.SUN;
        if (day.dayValue == 6 || day.dayValue == 0) {
            System.out.println("Work at home!");   //输出 Work at home!
        } else {
            System.out.println("Work at office!");
        }
    }
}

enum Weekday {
    MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6), SUN(0);

    public final int dayValue;

    private Weekday(int dayValue) {
        this.dayValue = dayValue;
    }
}

这样就无需担心顺序的变化,新增枚举常量时,也需要指定一个int值。

给枚举类添加的字段也可以是非final类型,即让该字段可以在使用时被修改,但是不推荐这样做!

 

相关文章:

  • 2022-01-05
  • 2021-12-14
  • 2021-09-27
  • 2021-05-23
  • 2021-10-07
  • 2021-12-29
  • 2021-09-24
  • 2022-12-23
猜你喜欢
  • 2021-06-09
  • 2022-12-23
  • 2021-09-17
  • 2021-07-19
  • 2021-06-13
  • 2021-07-06
  • 2021-09-27
相关资源
相似解决方案