Java基本语法的几个笔记

1 需要注意的点

1.1 运算赋值操作

  1. 复合赋值运算中(如:+=、-=等),隐含了类型强制转换。如:
    byte b = 126;
    // 按常理2是int型,byte + int 结果应该是int,但这里会强转为byte
    b += 2;  // 结果会溢出
    System.out.println(b); // -128
    
  2. 三目运算不能单独存在,运算结果必须要有“接收方”
    OperationDemo.java:10: 错误: 不是语句
                   a > b ? a : b;
                         ^
    1 个错误
    
  3. 整数类型中byte、short、int、long四种的前三种在运算时都会先转换为int类型;
    byte a = 10;
    byte b = 20;
    // 事实上是byte = int + int,所以编译时会报错
    byte ret = a + b;
    
    OperationDemo.java:5: 错误: 不兼容的类型: 从int转换到byte可能会有损失
                   byte ret = a + b;
                                ^
    1 个错误
    
  4. 如果表达式的右边为常量,编译时会先将表达的进行计算,用结果替换原来的表达式,如:
    // 上述示例中ret = a + b,表达式右边是int型,左边是byte,有转换失真的风险所以编译会报错;
    // 但如果右边是常量则不会,byte ret = 10 + 20类似直接写byte ret = 30;
    byte ret = 10 + 20;
    

1.2 函数与方法

  1. 方法重载中如果返回值类型不一样,不构成方法重载。(想想看,返回值是可以强制类型转换的,那么编译器到底该给哪个方法呢?所以此处有歧异)
    public static int sum(int a, int b) {
       return a + b;
    }
    // 编译报错,方法重名了,仅返回值类型不同不构成方法重载
    public static float sum(int a, int b) {
       return (float) (a + b);
    }
    

1.3 数组

  1. 数组初始化的几种方式,主要有静态初始化(指定值)与动态初始化(指定长度);
  • 所谓的静态与动态区别是即时指定长度还是直接赋值;
  • Java中指定值有两种方式,一种是类型前缀,一种不加(所谓的标准格式与省略格式);
  • 在其他高级语言中如C++,静态初始化不能拆开写(即省略格式),但Java标准格式可以;
  • 动态初始化数组时,内存中全部写0,即int为0、float为0.0、对象为null、char为\u0000
    // 动态初始化,在创建数组时指定数组长度
    int[] array1 = new int[10];
    System.out.println(array1);
    int[] array2 = new int[10];
    System.out.println(array2);
    
    // 静态初始化,创建数组时直接以数据长度为准
    int[] array3 = new int[] {1, 2, 3, 4};
    System.out.println(array3);
    int[] array4 = {1, 2, 3, 4};
    System.out.println(array4);
    
    // 初始化可以先定义变量再赋值,但有一种情况例外
    int[] array5;
    array5 = new int[10];
    int[] array6;
    array6 = new int[] {1, 2, 3, 4};
    int[] array7;
    array7 = {1, 2, 3, 4}; // 注意:这种情况是非法的,编译报错
    

2 相关总结

2.1 类与对象

局部变量与成员变量的区别

  1. 定义的位置不一样
    • 局部变量:在方法的内部
    • 成员变量:在方法的外部,直接写在类中
  2. 作用范围不一样
    • 局部变量:只有在当前方法中才可以使用,出了方法则不可用
    • 成员变量:整个类中都可以使用
  3. 默认值不一样
    • 局部变量:没有默认值,使用前必须赋初始值
    • 成员变量:编译器会自动赋默认值
  4. 内存位置不一样
    • 局部变量:位于栈内存
    • 成员变量:位于堆内存
  5. 生命周期不一样
    • 局部变量:随着方法进栈而生,随着方法出栈而亡
    • 成员变量:随着对象的创建而诞生,随着对象被垃圾回收而消失

2.2 字符串

创建字符串常用的4种方法(3种构造函数方法+1种字面量直接创建)

  1. 构造函数String()
    String str = new String();   // 
    
  2. 构造函数String(char[] charArray)
    char[] charArray = {'A', 'B', 'C'};
    String str = new String(charArray);  // ABC
    
  3. 构造函数String(byte[] byteArray)
    byte[] byteArray = {97, 98, 99};
    String str = new String(byteArray); // abc
    
  4. 字面量
    String str = "string";   // string
    

字符串在内存的表现形式

  1. 不管通过什么方式创建的字符串,所有的字符串都是对象;
  2. 通过字面量的形式创建的字符串,指向的堆空间的一个字符串常量池(共用字符串对象);
  3. 通过对象通过字符串的构造方法创建的字符串,先转换成char数组,再在堆中生成对象指定这个数组;
public class StringDemo {
    public static void main(String[] args) {
        String str1 = "abc";
        String str2 = "abc";
        char[] charArray = {'a', 'b', 'c'};
        String str3 = new String(charArray);
        /**
         * 引用类型通过“==”比较的是地址
         * 通过字面量直接创建的字符串,指向的是堆中的“字符串常量池”
         * 通过char数组创建的字符串,在堆中指向char数组转换后的另一片地址空间str->堆1->堆2
         */
        System.out.println(str1 == str2);   // true
        System.out.println(str2 == str3);   // false
        System.out.println(str3 == str1);   // false
    }
}

2.3 接口的基本使用

抽象方法的定义 public abstract 返回类型 方法名(参数列表); 实现类中必须实现接口中的所有抽象方法,除非是抽象类。

public abstract void abstractMethod1();

public abstract void abstractMethod2();

public abstract void abstractMethod3();

public abstract void abstractMethod4();

默认方法的定义 public default 返回值类型 方法名(参数列表){} 接口的实现类中可以选择性地实现该方法,SDK8.0及以上支持。

/**
 * 默认方法(解决升级的问题)
 * 该方法实现类中可以被重写,也可以省略,因为这里有实现体
 */
public default void defaultMethod() {
    System.out.println("接口类的默认方法...");
}

静态方法 public static 返回类型 方法名(参数列表){} 该特性从SDK8.0及以后才支持

public static void show() {
    System.out.println("MyInterfaceAbstract static method..");
}

私有方法的定义 privat 返回值类型 方法名(参数列表){},这种方法的定义在SDK9.0及以后的版本才支持,解决默认方法中功能的抽象,分为普通方法与静态方法,静态方法只能通过接口名调用

// 普通私有方法
private void commonMethod() {
    System.out.println("common method...");
}
// 静态私有方法
private static void staticMethod() {
    // coding...
}

静态常量 public static final 数据类型 常量名 = 值 需要注意的是:常量命名使用大写;public static final 可以省略但效果一样。

public static final int NAME_LENGTH = 10;

需要注意的是:

  • 接口中不能有静态代码块static {}
  • 接口实现类可以同时实现多个接口 implements intA, intB
  • 如果多个接口中抽象方法重名,只需要实现一次即可,如果是默认方法则必须重写
  • 如果没有实现接口的所有方法,只能是抽象类
  • 如果继承的方法与接口的方法冲突,则继承的方法优先级较高
  • 类只能单继承,但接口可以多继承

2.4 包装类的使用

intIntegerString 之间的相互转换,其它基本数据类型以此类推

// int --> Integer
// Integer i = new Integer(1);
Integer a = Integer.valueOf(1);
Integer a1 = 1;

// Integer --> int
int b = a.intValue();
int b1 = a;

// String --> Integer
Integer c = Integer.valueOf("1");

// String --> int
int d = Integer.parseInt("1");

// Integer --> String
String e = c.toString();

// int --> String
String f = String.valueOf(1);

Leave a Reply