首页 > 编程语言 >01 | JAVA入门基础

01 | JAVA入门基础

时间:2022-09-02 08:26:05浏览次数:75  
标签:01 JAVA String 子类 public Person 方法 class 入门

  • 基本数据类型
    • 基本数据类型是CPU可以直接进行运算的类型。Java定义了以下几种基本数据类型:
    • 整数类型:byte,short,int,long
    • 浮点数类型:float,double
    • 字符类型:char
    • 布尔类型:boolean
  • char 类型可以保存中文
  • 有多行字符串 """"""
  • Java的字符串除了是一个引用类型外,还有个重要特点,就是字符串不可变.这个和C++不同

image-20220831101244907

  • Java的数组有几个特点:

    • 数组所有元素初始化为默认值,整型都是0,浮点型是0.0,布尔型是false

    • 数组一旦创建后,大小就不可改变。

    • 可以用数组变量.length获取数组大小

  • 判断相等

    • 要注意浮点数判断相等不能直接用==运算符;
    • 引用类型(字符串等)判断内容相等要使用equals(),注意避免NullPointerException
  • switch 的 语法糖 -> 不再需要 break

  • for each 循环

public class Main {
    public static void main(String[] args) {
        int[] ns = { 1, 4, 9, 16, 25 };
        for (int n : ns) {
            System.out.println(n);
        }
    }
}
  • 数组排序
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] ns = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };
        Arrays.sort(ns);
        System.out.println(Arrays.toString(ns));
    }
}

image-20220831102102133

  • 二维数组

    • 二维数组的每个数组元素的长度并不要求相同,例如,可以这么定义ns数组:

      int[][] ns = {
          { 1, 2, 3, 4 },
          { 5, 6 },
          { 7, 8, 9 }
      };
      

      这个二维数组在内存中的结构如下:

                          ┌───┬───┬───┬───┐
               ┌───┐  ┌──▶│ 1 │ 2 │ 3 │ 4 │
      ns ─────▶│░░░│──┘   └───┴───┴───┴───┘
               ├───┤      ┌───┬───┐
               │░░░│─────▶│ 5 │ 6 │
               ├───┤      └───┴───┘
               │░░░│──┐   ┌───┬───┬───┐
               └───┘  └──▶│ 7 │ 8 │ 9 │
                          └───┴───┴───┘
      
    • 打印二维数组 使用Java标准库的Arrays.deepToString()

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[][] ns = {
            { 1, 2, 3, 4 },
            { 5, 6, 7, 8 },
            { 9, 10, 11, 12 }
        };
        System.out.println(Arrays.deepToString(ns));
    }
}

  • 命令行参数类型是String[]数组;

  • Java标准库提供的核心类,包括:

    • 字符串
    • 包装类型
    • JavaBean
    • 枚举
    • 常用工具类
  • Java语言本身提供的机制,包括:

    • package
    • classpath
    • jar
  • 一个Java源文件可以包含多个类的定义,但只能定义一个public类,且public类名必须与文件名一致。如果要定义多个public类,必须拆到多个Java源文件中。

  • 在OOP中,classinstance是“模版”和“实例”的关系;

    定义class就是定义了一种数据类型,对应的instance是这种数据类型的实例;

    class定义的field,在每个instance都会拥有各自的field,且互不干扰;

    通过new操作符创建新的instance,然后用变量指向它,即可通过变量来引用这个instance

    访问实例字段的方法是变量名.字段名

    指向instance的变量都是引用变量。

    在JAVA中没有C++的 :: 标识符!就算是类方法也用.

  • 可变参数

    • 可变参数用类型...定义,可变参数相当于数组类型:

    • class Group {
          private String[] names;
      
          public void setNames(String... names) {
              this.names = names;
          }
      }
      

      上面的setNames()就定义了一个可变参数。调用时,可以这么写:

      Group g = new Group();
      g.setNames("Xiao Ming", "Xiao Hong", "Xiao Jun"); // 传入3个String
      g.setNames("Xiao Ming", "Xiao Hong"); // 传入2个String
      g.setNames("Xiao Ming"); // 传入1个String
      g.setNames(); // 传入0个String
      
    • C++ 中的可变参数可以用模板来做,也可以用 initial_list<> 来做

    • C 语言中的可变参数 printf 是专门有一个头文件来进行处理

  • 基本类型参数的传递,是调用方值的复制。双方各自的后续修改,互不影响。这个和 python 如出一辙。

  • 引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方(因为指向同一个对象嘛)。这个和 python 如出一辙

  • 构造方法的名称就是类名。构造方法的参数没有限制,在方法内部,也可以编写任意语句。但是,和普通方法相比,构造方法没有返回值(也没有void),调用构造方法,必须用new操作符,这个就不如C++灵活

  • 没有在构造方法中初始化字段时,引用类型的字段默认是null,数值类型的字段用默认值,int类型默认值是0,布尔类型默认值是false

  • 在Java中,创建对象实例的时候,按照如下顺序进行初始化:

    1. 先初始化字段,例如,int age = 10;表示字段初始化为10double salary;表示字段默认初始化为0String name;表示引用类型字段默认初始化为null
    2. 执行构造方法的代码进行初始化。

    因此,构造方法的代码由于后运行,所以,new Person("Xiao Ming", 12)的字段值最终由构造方法的代码确定。

  • 可以定义多个构造方法,在通过new操作符调用的时候,编译器通过构造方法的参数数量、位置和类型自动区分:

  • String类提供了多个重载方法indexOf(),可以查找子串:

    • int indexOf(int ch):根据字符的Unicode码查找;
    • int indexOf(String str):根据字符串查找;
    • int indexOf(int ch, int fromIndex):根据字符查找,但指定起始位置;
    • int indexOf(String str, int fromIndex)根据字符串查找,但指定起始位置。
  • Java使用extends关键字来实现继承:注意:子类自动获得了父类的所有字段,严禁定义与父类重名的字段!

  • 继承树

    • 注意到我们在定义Person的时候,没有写extends。在Java中,没有明确写extends的类,编译器会自动加上extends Object。所以,任何类,除了Object,都会继承自某个类。下图是PersonStudent的继承树:

      ┌───────────┐
      │  Object   │
      └───────────┘
            ▲
            │
      ┌───────────┐
      │  Person   │
      └───────────┘
            ▲
            │
      ┌───────────┐
      │  Student  │
      └───────────┘
      
    • Java只允许一个class继承自一个类,因此,一个类有且仅有一个父类。只有Object特殊,它没有父类。

      类似的,如果我们定义一个继承自PersonTeacher,它们的继承树关系如下:

             ┌───────────┐
             │  Object   │
             └───────────┘
                   ▲
                   │
             ┌───────────┐
             │  Person   │
             └───────────┘
                ▲     ▲
                │     │
                │     │
      ┌───────────┐ ┌───────────┐
      │  Student  │ │  Teacher  │
      └───────────┘ └───────────┘
      
  • protected修饰的字段可以被子类访问:因此,protected关键字可以把字段和方法的访问权限控制在继承树内部,一个protected字段和方法可以被其子类,以及子类的子类所访问。

  • super关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName

  • 在Java中,任何class的构造方法,第一行语句必须是调用父类的构造方法。如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句super();,所以,Student类的构造方法实际上是这样:

    class Student extends Person {
        protected int score;
    
        public Student(String name, int age, int score) {
            super(); // 自动调用父类的构造方法
            this.score = score;
        }
    }
    
  • 如果父类没有默认的构造方法,子类就必须显式调用super()并给出参数以便让编译器定位到父类的一个合适的构造方法。

    这里还顺带引出了另一个问题:即子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的。

  • 只要某个class没有final修饰符,那么任何类都可以从该class继承。

  • 从Java 15开始,允许使用sealed修饰class,并通过permits明确写出能够从该class继承的子类名称。

    例如,定义一个Shape类:

    public sealed class Shape permits Rect, Circle, Triangle {
        ...
    }
    

    上述Shape类就是一个sealed类,它只允许指定的3个类继承它。

    public final class Rect extends Shape {...}
    

    是没问题的,因为Rect出现在Shapepermits列表中。

  • instanceof实际上判断一个变量所指向的实例是否是指定类型,或者这个类型的子类。如果一个引用变量为null,那么对任何instanceof的判断都为false为了向下转型安全

    • Person p = new Student();
      if (p instanceof Student) {
          // 只有判断成功才会向下转型:
          Student s = (Student) p; // 一定会成功
      }
      
  • Override和Overload不同的是,如果方法签名不同,就是Overload,Overload方法是一个新方法;如果方法签名相同,并且返回值也相同,就是Override

    • class Person {
          public void run() { … }
      }
      
      class Student extends Person {
          // 不是Override,因为参数不同:
          public void run(String s) { … }
          // 不是Override,因为返回值不同:
          public int run() { … }
      }
      

      加上@Override可以让编译器帮助检查是否进行了正确的覆写。希望进行覆写,但是不小心写错了方法签名,编译器会报错。

  • 多态的特性就是,运行期才能动态决定调用的子类方法。对某个类型调用某个方法,执行的实际方法可能是某个子类的覆写方法。

  • Object定义了几个重要的方法:

    • toString():把instance输出为String
    • equals():判断两个instance是否逻辑相等;
    • hashCode():计算一个instance的哈希值。
  • 在子类的覆写方法中,如果要调用父类的被覆写的方法,可以通过super来调用

    • class Person {
          protected String name;
          public String hello() {
              return "Hello, " + name;
          }
      }
      
      Student extends Person {
          @Override
          public String hello() {
              // 调用父类的hello()方法:
              return super.hello() + "!";
          }
      }
      
  • 继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final。用final修饰的方法不能被Override而C++中是visual 关键字来说明是否可重写

    class Person {
        protected String name;
        public final String hello() {
            return "Hello, " + name;
        }
    }
    
    Student extends Person {
        // compile error: 不允许覆写
        @Override
        public String hello() {
        }
    }
    
  • 如果父类的方法本身不需要实现任何功能,仅仅是为了定义方法签名,目的是让子类去覆写它,那么,可以把父类的方法声明为抽象方法:也就是 C++ 中的纯虚方法

    class Person {
        public abstract void run();
    }
    
  • 因为这个抽象方法本身是无法执行的,所以,Person类也无法被实例化。编译器会告诉我们,无法编译Person类,因为它包含抽象方法。

    必须把Person类本身也声明为abstract,才能正确编译它

    abstract class Person {
        public abstract void run();
    }
    
    
  • 抽象类:如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰。

    因为无法执行抽象方法,因此这个类也必须申明为抽象类(abstract class)。

    使用abstract修饰的类就是抽象类。我们无法实例化一个抽象类:

  • 接口:如果一个抽象类没有字段,所有方法全部都是抽象方法。

    • abstract class Person {
          public abstract void run();
          public abstract String getName();
      }
      
    • 在Java中,使用interface可以声明一个接口:

      interface Person {
          void run();
          String getName();
      }
      
    • 当一个具体的class去实现一个interface时,需要使用implements关键字。举个例子:

    • class Student implements Person {
          private String name;
      
          public Student(String name) {
              this.name = name;
          }
      
          @Override
          public void run() {
              System.out.println(this.name + " run");
          }
      
          @Override
          public String getName() {
              return this.name;
          }
      }
      
    • 我们知道,在Java中,一个类只能继承自另一个类,不能从多个类继承。但是,一个类可以实现多个interface,例如:

      class Student implements Person, Hello { // 实现了两个interface
          ...
      }
      
  • 接口继承:一个interface可以继承自另一个interfaceinterface继承自interface使用extends,它相当于扩展了接口的方法。

    • interface Hello {
          void hello();
      }
      
      interface Person extends Hello {
          void run();
          String getName();
      }
      
  • 继承关系

    • 合理设计interfaceabstract class的继承关系,可以充分复用代码。一般来说,公共逻辑适合放在abstract class中,具体逻辑放到各个子类,而接口层次代表抽象程度。可以参考Java的集合类定义的一组接口、抽象类以及具体子类的继承关系:

      ┌───────────────┐
      │   Iterable    │
      └───────────────┘
              ▲                ┌───────────────────┐
              │                │      Object       │
      ┌───────────────┐        └───────────────────┘
      │  Collection   │                  ▲
      └───────────────┘                  │
              ▲     ▲          ┌───────────────────┐
              │     └──────────│AbstractCollection │
      ┌───────────────┐        └───────────────────┘
      │     List      │                  ▲
      └───────────────┘                  │
                    ▲          ┌───────────────────┐
                    └──────────│   AbstractList    │
                               └───────────────────┘
                                      ▲     ▲
                                      │     │
                                      │     │
                           ┌────────────┐ ┌────────────┐
                           │ ArrayList  │ │ LinkedList │
                           └────────────┘ └────────────┘
      
    • 在使用的时候,实例化的对象永远只能是某个具体的子类,但总是通过接口去引用它,因为接口比抽象类更抽象:

      List list = new ArrayList(); // 用List接口引用具体子类的实例
      Collection coll = list; // 向上转型为Collection接口
      Iterable it = coll; // 向上转型为Iterable接口
      
  • default 方法

    • 在接口中,可以定义default方法。例如,把Person接口的run()方法改为default方法:

    • 实现类可以不必覆写default方法。default方法的目的是,当我们需要给接口新增一个方法时,会涉及到修改全部子类。如果新增的是default方法,那么子类就不必全部修改,只需要在需要覆写的地方去覆写新增方法。

      default方法和抽象类的普通方法是有所不同的。因为interface没有字段,default方法无法访问字段,而抽象类的普通方法可以访问实例字段。但是可以通过内部函数调用来访问字段

  • 接口的静态字段

    • 因为interface是一个纯抽象类,所以它不能定义实例字段。但是,interface是可以有静态字段的,并且静态字段必须为final类型:.

    • public interface Person {
          public static final int MALE = 1;
          public static final int FEMALE = 2;
      }
      

      实际上,因为interface的字段只能是public static final类型,所以我们可以把这些修饰符都去掉,上述代码可以简写为:

      public interface Person {
          // 编译器会自动加上public statc final:
          int MALE = 1;
          int FEMALE = 2;
      }
      
  • 包作用域:位于同一个包的类,可以访问包作用域的字段和方法。不用publicprotectedprivate修饰的字段和方法就是包作用域。例如,Person类定义在hello包下面:

    • package hello;
      
      public class Person {
          // 包作用域:
          void hello() {
              System.out.println("Hello!");
          }
      }
      

      Main类也定义在hello包下面:

      package hello;
      
      public class Main {
          public static void main(String[] args) {
              Person p = new Person();
              p.hello(); // 可以调用,因为Main和Person在同一个包
          }
      }
      
  • import static 语法它可以导入可以导入一个类的静态字段和静态方法:很少使用。

    • package main;
      
      // 导入System类的所有静态字段和静态方法:
      import static java.lang.System.*;
      
      public class Main {
          public static void main(String[] args) {
              // 相当于调用System.out.println(…)
              out.println("Hello, world!");
          }
      }
      
  • 找包的流程

    • ava编译器最终编译出的.class文件只使用完整类名,因此,在代码中,当编译器遇到一个class名称时:

      • 如果是完整类名,就直接根据完整类名查找这个class
      • 如果是简单类名,按下面的顺序依次查找:
        • 查找当前package是否存在这个class
        • 查找import的包是否包含这个class
        • 查找java.lang包是否包含这个class
    • 我们来看一个例子:

      // Main.java
      package test;
      
      import java.text.Format;
      
      public class Main {
          public static void main(String[] args) {
              java.util.List list; // ok,使用完整类名 -> java.util.List
              Format format = null; // ok,使用import的类 -> java.text.Format
              String s = "hi"; // ok,使用java.lang包的String -> java.lang.String
              System.out.println(s); // ok,使用java.lang包的System -> java.lang.System
              MessageFormat mf = null; // 编译错误:无法找到MessageFormat: MessageFormat cannot be resolved to a type
          }
      }
      

      因此,编写class的时候,编译器会自动帮我们做两个import动作:

      • 默认自动import当前package的其他class
      • 默认自动import java.lang.*
      • 注意:自动导入的是java.lang包,但类似java.lang.reflect这些包仍需要手动导入。
  • public

    • 定义为publicclassinterface可以被其他任何类访问:
    • 定义为publicfieldmethod可以被其他类访问,前提是首先有访问class的权限:
  • private

    • 定义为privatefieldmethod无法被其他类访问:
    • 确切地说,private访问权限被限定在class的内部,而且与方法声明顺序无关。推荐把private方法放到后面,因为public方法定义了类对外提供的功能,阅读代码的时候,应该先关注public方法:
    • 由于Java支持嵌套类,如果一个类内部还定义了嵌套类,那么,嵌套类拥有访问private的权限:
  • protected

    • protected作用于继承关系。定义为protected的字段和方法可以被子类访问,以及子类的子类
  • package

    • 最后,包作用域是指一个类允许访问同一个package的没有publicprivate修饰的class,以及没有publicprotectedprivate修饰的字段和方法。

    • 最后,包作用域是指一个类允许访问同一个package的没有publicprivate修饰的class,以及没有publicprotectedprivate修饰的字段和方法。

      package abc;
      // package权限的类:
      class Hello {
          // package权限的方法:
          void hi() {
          }
      }
      

      只要在同一个包,就可以访问package权限的classfieldmethod

      package abc;
      
      class Main {
          void foo() {
              // 可以访问package权限的类:
              Hello h = new Hello();
              // 可以调用package权限的方法:
              h.hi();
          }
      }
      
  • 一个.java文件只能包含一个public类,但可以包含多个非public类。如果有public类,文件名必须和public类的名字相同。

标签:01,JAVA,String,子类,public,Person,方法,class,入门
From: https://www.cnblogs.com/mmxingye/p/16648464.html

相关文章

  • 02 | JAVA内部类
    java内部类Java的内部类分为好几种,通常情况用得不多,但也需要了解它们是如何使用的。1.InnerClass如果一个类定义在另一个类的内部,这个类就是InnerClass:它与普通类有......
  • 04 | JAVA模块
    模块jar只是用于存放class的容器,它并不关心class之间的依赖。从Java9开始引入的模块,主要是为了解决“依赖”这个问题。如果a.jar必须依赖另一个b.jar才能运行,那我们应该......
  • 05 | JAVA字符串
    字符串Strings1="Hello!";实际上字符串在String内部是通过一个char[]数组表示的,因此,按下面的写法也是可以的:Strings2=newString(newchar[]{'H','e','l','l......
  • 06 | JAVA的StringBuilder高效拼接字符串
    StringBuilder如果用+来拼接字符串速度满。我们可以提前用StringBuilder来申请一大块的内存。把他想象成一个容器。为了能高效拼接字符串,Java标准库提供了StringBuil......
  • 07 | JAVA的StringJoiner对象专门拼接字符串
    StringJoiner对象专门用来拼接字符串importjava.util.StringJoiner;publicclassMain{publicstaticvoidmain(String[]args){String[]names={......
  • 08 | JAVA包装类型
    包装类型我们已经知道,Java的数据类型分两种:基本类型:byte,short,int,long,boolean,float,double,char引用类型:所有class和interface类型引用类型可以赋值为null,表示空,但基本......
  • 09 | JavaBean一种类的格式
    JavaBean在Java中,有很多class的定义都符合这样的规范:若干private实例字段;通过public方法来读写实例字段。如果字段是xyz,那么读写方法名分别以get和set开头,并且后......
  • 10 | JAVA枚举类enum
    枚举类enumpublicclassMain{publicstaticvoidmain(String[]args){Weekdayday=Weekday.SUN;if(day==Weekday.SAT||day==Weekda......
  • 11 | JAVA纪录类Record
    纪录类(也是一种不变类)使用String、Integer等类型的时候,这些类型都是不变类,一个不变类具有以下特点:定义class时使用final,无法派生子类;每个字段使用final,保证创建实例......
  • Java-JDBC和mysql的使用
    1.MySqlJDBC(JavaDataBaseConnection)是通过JAVA访问数据库,需要对数据库有基本的理解和应用。MySql作为常见的数据库,在中小型网站经常被使用;其中包含了mysql服务器......