数据类型

  • 整型
    • int/32
    • short/16
    • long/64
    • byte/8
  • 浮点类型
    • float/32
    • double/64
  • char 类型
    • char/16
  • boolean 类型

    • boolean/1

      包装类型

      把一个基本类型视为对象(引用类型)

  • 引用类型不能用 == 来比较两个值是否相等,要实用 equals() 比较

企业微信20210617-121506@2x.png

  1. // 自动装箱(Auto Boxing)
  2. Integer n = 100; // 编译器自动使用Integer.valueOf(int)
  3. // 自动拆箱(Auto Unboxing)
  4. int x = n; // 编译器自动使用Integer.intValue()

缓存池

  • new Integer(123) 每次都会新建一个对象
  • Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用
    1. Integer x = new Integer(123);
    2. Integer y = new Integer(123);
    3. System.out.println(x == y); // false
    4. Integer z = Integer.valueOf(123);
    5. Integer k = Integer.valueOf(123);
    6. System.out.println(z == k); // true
    1. public static Integer valueOf(int i) {
    2. if (i >= IntegerCache.low && i <= IntegerCache.high)
    3. return IntegerCache.cache[i + (-IntegerCache.low)];
    4. return new Integer(i);
    5. }

    编译器会在缓冲池范围内的基本类型自动装箱过程调用 valueOf() 方法,因此多个 Integer 实例使用自动装箱来创建并且值相同,那么就会引用相同的对象。

  1. Integer m = 123;
  2. Integer n = 123;
  3. System.out.println(m == n); // true

String

被声明为 final,不可被继承

  1. public final class String
  2. implements java.io.Serializable, Comparable<String>, CharSequence {
  3. /** The value is used for character storage. */
  4. private final char value[];

String.intern()

使用 String.intern() 可以保证相同内容的字符串变量引用同一的内存对象。

  1. String s1 = new String("aaa");
  2. String s2 = new String("aaa");
  3. System.out.println(s1 == s2); // false
  4. String s3 = s1.intern();
  5. System.out.println(s1.intern() == s3); // true
  6. // 使用双引号的形式创建字符串实例,会自动地将新建的对象放入 String Pool 中
  7. String s4 = "bbb";
  8. String s5 = "bbb";
  9. System.out.println(s4 == s5); // true

运算

参数传递

Java没有栈上对象,只有堆上对象,Java的引用都是指针

  1. // 第一个例子:基本类型
  2. void foo(int value) {
  3. value = 100;
  4. }
  5. foo(num); // num 没有被改变
  6. // 第二个例子:没有提供改变自身方法的引用类型
  7. void foo(String text) {
  8. text = "windows";
  9. }
  10. foo(str); // str 也没有被改变
  11. // 第三个例子:提供了改变自身方法的引用类型
  12. StringBuilder sb = new StringBuilder("iphone");
  13. void foo(StringBuilder builder) {
  14. builder.append("4");
  15. }
  16. foo(sb); // sb 被改变了,变成了"iphone4"。
  17. // 第四个例子:提供了改变自身方法的引用类型,但是不使用,而是使用赋值运算符。
  18. StringBuilder sb = new StringBuilder("iphone");
  19. void foo(StringBuilder builder) {
  20. builder = new StringBuilder("ipad");
  21. }
  22. foo(sb); // sb 没有被改变,还是 "iphone"。

继承

访问权限

企业微信20210617-144330@2x.png

抽象类与接口

抽象类

使用 abstract 关键字进行声明,抽象类不能被实例化,需要继承抽象类才能实例化其子类。

  1. public abstract class AbstractClassExample {
  2. protected int x;
  3. private int y;
  4. public abstract void func1();
  5. public void func2() {
  6. System.out.println("func2");
  7. }
  8. }
  9. public class AbstractExtendClassExample extends AbstractClassExample {
  10. @Override
  11. public void func1() {
  12. System.out.println("func1");
  13. }
  14. }
  15. // AbstractClassExample ac1 = new AbstractClassExample(); // 'AbstractClassExample' is abstract; cannot be instantiated
  16. AbstractClassExample ac2 = new AbstractExtendClassExample();
  17. ac2.func1();

接口

接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。
接口的字段默认都是 static 和 final 的。

  1. public interface InterfaceExample {
  2. void func1();
  3. default void func2(){
  4. System.out.println("func2");
  5. }
  6. int x = 123;
  7. // int y; // Variable 'y' might not have been initialized
  8. public int z = 0; // Modifier 'public' is redundant for interface fields
  9. // private int k = 0; // Modifier 'private' not allowed here
  10. // protected int l = 0; // Modifier 'protected' not allowed here
  11. // private void fun3(); // Modifier 'private' not allowed here
  12. }
  13. public class InterfaceImplementExample implements InterfaceExample {
  14. @Override
  15. public void func1() {
  16. System.out.println("func1");
  17. }
  18. }
  19. // InterfaceExample ie1 = new InterfaceExample(); // 'InterfaceExample' is abstract; cannot be instantiated
  20. InterfaceExample ie2 = new InterfaceImplementExample();
  21. ie2.func1();
  22. System.out.println(InterfaceExample.x);

关键字

final

  • 数据:相当于常量
    • 基本类型:数值不变
    • 引用类型:引用不变
  • 方法:不能被子类重写
  • 类:不能被继承 ```javascript final int x = 1; // x = 2; // cannot assign value to final variable ‘x’ final A y = new A(); y.a = 1;
  1. <a name="T4pKG"></a>
  2. ## static
  3. - 静态变量:类的所有实例共享静态变量
  4. ```javascript
  5. public class A {
  6. private int x; // 实例变量
  7. private static int y; // 静态变量
  8. public static void main(String[] args) {
  9. // int x = A.x; // Non-static field 'x' cannot be referenced from a static context
  10. A a = new A();
  11. int x = a.x;
  12. int y = A.y;
  13. }
  14. }
  • 静态方法:方法中不能有 this 和 super 关键字。 ```javascript public class A { private static int x; private int y;

    public static void func1(){

    1. int a = x;
    2. // int b = y; // Non-static field 'y' cannot be referenced from a static context
    3. // int b = this.y; // 'A.this' cannot be referenced from a static context

    } }

  1. - 静态内部类:不能访问外部类的非静态的变量和方法。
  2. ```javascript
  3. public class OuterClass {
  4. class InnerClass {
  5. }
  6. static class StaticInnerClass {
  7. }
  8. public static void main(String[] args) {
  9. // InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
  10. OuterClass outerClass = new OuterClass();
  11. InnerClass innerClass = outerClass.new InnerClass();
  12. StaticInnerClass staticInnerClass = new StaticInnerClass();
  13. }
  14. }

反射(reflective)

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

参考资料

  1. java 全栈知识体系
  2. Java 到底是值传递还是引用传递?