Java基础补充(一)—— 面向对象编程

189 阅读4分钟

面向对象编程

  • 面向对象基础

    • 方法

      • setter()可以添加条件检查(不允许传入null和空字符串)

      • 可变参数

        class Group {
            private String[] names;
            public void setNames(String... names) {
              	this.name = name;
            }
        }
        
        Group g = new Group();
        g.setName("Xiao Ming", "Xiao Hong");
        g.setName();
        

        可变参数 -> String[]: 但是调用方需要自己构造String[]; 可以传入null

        class Group {
            private String[] names;
            public void setNames(String[] names) {
              	this.name = name;
            }
        }
        
        Group g = new Group();
        g.setNames(new String[] {"Xiao Ming", "Xiao Hong"});
        g.setNames(null);
        

        可变参数保证无法传入null,传入0个参数时,实为空数组。

    • 构造方法

      • 如果自定义了一个Constructor,那么编译器不再自动创建默认Constructor。
    • 继承

      • Java 14开始,判断instanceof后可以直接转型为指定变量,避免再次强制转型。

        Object obj = "Hello";
        if (obj instanceof String s) {
              System.out.println(s.toUpperCase());
        }
        
      • 继承是is关系,组合是has关系

      • 抽象类和接口

        抽象类 接口
        extend implements
        成员都是public, 字段static和final
        一个类只可以继承一个抽象类 一个类可以继承多个接口
        代码复用,不同类具有某些相同行为,剩下留给自己实现 行为约束,强制不同类有相同行为
        IS-A(玻璃杯->杯) LIKE-A(空调->制冷机)
      • 关键字权限

        关键字 private default protected public
        类内 Y Y Y Y
        包内 N Y Y Y
        包外子类 N N Y Y
        包外非子类 N N N Y
  • Java核心类

    • String

      • 替换子串

        • replace(char, char)/ replace(CharSequence, CharSequence)
        • replaceFirst(String regex, String replacement)
        • replaceAll(String regex, String replacement)
      • 去除空白字符

        • trim()
        • strip()/stripLeading()/stripTrailing()中文空格字符\u3000也会被移除
      • 分割字符串

        • split(String regex)
      • 格式化字符串

        • formattedformat()

          public class Main {
              public static void main(String[] args) {
                	  String s = "Hi %s, your score is %d!";
                	  System.out.println(s.formatted("Alice", 80));
                	  System.out.println(String.format("Hi %s, your score is %.2f!", "Bob", 59.5));
              }
          }
          
      • 类型转换

        • valueOf()

          String.valueOf(123); //"123"
          String.valueOf(true); //"true"
          
      • 转换为char[]

        char[] cs = "Hello".toCharArray();
        String s = new String(cs);
        

        new String(char[])创建新的String实例时,是复制了一份char[]数组,所以改变了外部char[]不会改变String实例内部char[]

      • 字符编码

        byte[] b1 = "Hello".getBytes("UTF-8");
        

        Java的Stringchar在内存中总是以Unicode编码表示。

    • StringBuilder

      • 链式操作(实现思想)

        public class Main {
            public static void main(String[] args) {
              	StringBuilder sb = new StringBuilder(1024);
              	sb.append("Mr").
                  .append("Bob").
                  .insert(0, "Hello, ");
            }
        }
        

        append()方法会返回this,这样就可以不断调用自身的其他方法。

        应用:

        class Adder {
            private int sum = 0;
            public Adder add(int n) {
              	sum += n;
              	return this;
            }
        }
        
    • StringJoiner

      public class Main {
          public static void main(String[] args) {
            	String[] names = {"Bob", "Alice", "Grace"};
            	// 开头Hello,结尾!
            	StringJoiner sj = new StringJoiner(", ", "Hello ", "!");
            	for (String name: names) {
                	sj.add(name);
              }
            	System.out.println(sj.toString());
            	// Hello Bob, Alice, Grace!
          }
      }
      
    • JavaBean

      • Introspector枚举JavaBean所有属性

        public class Main {
            public static void main(String[] args) throws Exception {
              	BeanInfo info = Introspector.getBeanInfo(Person.class);
              	for (PropertyDescriptor pd: info.getPropertyDescriptions()) {
                  	System.out.println(pd.getName());
                  	System.out.println(" " + pd.getReadMethod());
                  	System.out.println(" " + pd.getWriteMethod());
                }
            }
        }
        
        class Person {
            private String name;
            private int age;
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public int getAge() {
                return age;
            }
            public void setAge(int age) {
                this.age = age;
            }
        }
        
        /*
        age
          public int Person.getAge()
          public void Person.setAge(int)
        class
          public final native java.lang.Class java.lang.Object.getClass()
          null
        name
          public java.lang.String Person.getName()
          public void Person.setName(java.lang.String)
          */
        

        class属性是从Object继承的getClass()方法带来的。

    • 枚举类Enum

      • enum

        • 总是继承java.lang.Enum
        • 只能定义出enum的实例,而无法通过new创建enum的实例
        • 定义的每个实例都是引用类型的唯一实例
        • 可以用于switch语句
        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 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;
            }
          	@Override
            public String toString() {
                return this.chinese;
            }
        }
        
        public class Main {
            public static void main(String[] args) {
                Weekday day = Weekday.SUN;
                if (day.dayValue == 6 || day.dayValue == 0) {
                    System.out.println("Today is " + day + ". Work at home!");
                } else {
                    System.out.println("Today is " + day + ". Work at office!");
                }
            }
        }
        
      • switch

        public class Main {
            public static void main(String[] args) {
                Weekday day = Weekday.SUN;
                switch(day) {
                case MON:
                case TUE:
                case WED:
                case THU:
                case FRI:
                    System.out.println("Today is " + day + ". Work at office!");
                    break;
                case SAT:
                case SUN:
                    System.out.println("Today is " + day + ". Work at home!");
                    break;
                default:
                    throw new RuntimeException("cannot process " + day);
                }
            }
        }
        
        enum Weekday {
            MON, TUE, WED, THU, FRI, SAT, SUN;
        }
        
    • 记录类Record(Java 14)

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

      改写为class为:

      public final class Point extends Record {
          private final int x;
          private final int y;
      
          public Point(int x, int y) {
              this.x = x;
              this.y = y;
          }
      
          public int x() {
              return this.x;
          }
      
          public int y() {
              return this.y;
          }
      
          public String toString() {
              return String.format("Point[x=%s, y=%s]", x, y);
          }
      
          public boolean equals(Object o) {
              ...
          }
          public int hashCode() {
              ...
          }
      }
      
    • Random

      • SecureRandom产生安全的随机数:种子是通过CPU的热噪声、读写磁盘的字节、网络流量等各种随机事件产生的“熵”。