coding-practicing

java

类型

Java的数据类型分两种:

基本类型:byte,short,int,long,boolean,float,double,char

引用类型:所有class和interface类型

引用类型可以赋值为null,表示空,但基本类型不能赋值为null

包装类型

将基本类型类型用类封装

Java核心库为每种基本类型都提供了对应的包装类型,如java.lang.Boolean,java.lang.Double

核心库提供的包装类都是不变类(final),创建后是不变的

@jdk.internal.ValueBased
public final class Integer extends Number
        implements Comparable<Integer>, Constable, ConstantDesc {
    private final int value;        
}

包装类对比

核心库提供的包装类实例必须使用equals对比不能使用==

 Integer a = Integer.valueOf(111111111);
 Integer b = Integer.valueOf(111111111);
 System.out.println("a==b  :" + (a == b));
 System.out.println("equals:" + (a.equals(b)));

枚举

enum定义的类型是class,有以下几个特点:

enum Weekday {
    MON(1, "星期一"), TUE(2, "星期二"), WED(3, "星期三"), THU(4, "星期四"), FRI(5, "星期五"), SAT(6, "星期六"), SUN(0, "星期日");

    public final int dayValue;
    private final String chinese;

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

    // 默认情况下,对枚举常量调用toString()会返回和name()一样的字符串
    // toString()可以被覆写,而name()则不行
    @Override
    public String toString() {
        return this.chinese;
    }
}

JavaBean

读写方法符合以下这种命名规范的class被称为JavaBean

// 读方法:
public Type getXyz()
// 写方法:
public void setXyz(Type value)

JavaBean主要用来传递数据,即把一组数据组合成一个JavaBean便于传输。 此外,JavaBean可以方便地被IDE工具分析,生成读写属性的代码,主要用在图形界面的可视化设计中。

枚举JavaBean属性

可以使用Java核心库提供的Introspector枚举JavaBean的所有属性

BeanInfo info = Introspector.getBeanInfo(Person.class);
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
    System.out.println(pd.getName());
    System.out.println("  " + pd.getReadMethod());
    System.out.println("  " + pd.getWriteMethod());
}
// 输出
// age
//   public int base.Person.getAge()
//   public void base.Person.setAge(int)
// class
//   public final native java.lang.Class java.lang.Object.getClass()
//   null
// name
//   public java.lang.String base.Person.getName()
//   public void base.Person.setName(java.lang.String)

其中”class”是从Object继承的getClass()方法带来的

记录类

从Java 14开始,引入了新的Record类

public class Main {
    public static void main(String[] args) {
        Point p = new Point(123, 456);
        System.out.println(p.x());
        System.out.println(p.y());
        System.out.println(p);
    }
}

public record Point(int x, int y) {}

除了用final修饰class以及每个字段外,编译器还自动为我们创建了构造方法,和字段名同名的方法,以及覆写toString()、equals()和hashCode()方法。

换句话说,使用record关键字,可以一行写出一个不变类。

日志

Commons Logging和Log4j: 一个负责充当日志API,一个负责实现日志底层,搭配使用非常方便

包管理

Functional Programming,函数式编程

把只定义了单方法的接口称之为FunctionalInterface,用注解@FunctionalInterface标记,

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

Lambda表达式

// 使用Lambda表达式,我们就可以不必编写FunctionalInterface接口的实现类,从而简化代码:
Arrays.sort(array, (s1, s2) -> {
    return s1.compareTo(s2);
});
public class FunctionalProgrammingDemo {
    static int cmp(String s1, String s2) {
        return s1.compareTo(s2);
    }

    // 从Java 8开始,我们可以用Lambda表达式替换单方法接口
    void SortStrings(String[] strs) {
        Arrays.sort(strs, new Comparator<String>() {
            public int compare(String s1, String s2) {
                return s1.compareTo(s2);
            }
        });
    }

    /*
     * Lambda
     * 参数是(s1, s2),参数类型可以省略,因为编译器可以自动推断出String类型。-> { ...}
     * 表示方法体,所有代码写在内部即可。Lambda表达式没有class定义,因此写法非常简洁。
     */
    void LambdaSortStrings(String[] strs) {
        Arrays.sort(strs, (s1, s2) -> {
            return s1.compareTo(s2);
        });
        // 等同于 Arrays.sort(array, (s1, s2) -> s1.compareTo(s2));
    }

    // 还可以引入签名一致的方法
    // 这里,方法签名只看参数类型和返回类型,不看方法名称,也不看类的继承关系
    public static void main(String[] args) {
        String[] array = new String[] { "Apple", "Orange", "Banana", "Lemon" };
        Arrays.sort(array, FunctionalProgrammingDemo::cmp);
        System.out.println(String.join(", ", array));
    }
}

参考