菜鸟Java基础教程 2.Java 基础语法

本文全面介绍Java基础语法,涵盖名词概念,如类、对象等;展示第一个Java程序及运行步骤;阐述基本语法、标识符、修饰符、变量等规则;介绍数组、枚举用法;讲解关键字、注释、空行知识;还涉及继承、接口概念及源程序与编译型运行区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java 基础语法

1. 名词介绍

一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。

对象 实例

对象:对象是类的一个实例有状态和行为。例如,一条狗是一个对象,
+ 它的状态有:颜色、名字、品种
+ 行为有 :摇尾巴、叫、吃等

类 模板

  • :类是一个模板,它描述一类对象的行为和状态。

方法 行为

  • 方法:方法就是行为,一个类可以有很多方法。逻辑运算、数据修改以及所有动作都是在方法中完成的。

实例变量 状态

  • 实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。

类和对象是面向对象编程中的两个核心概念,它们之间有一定的关系,但并不是类是抽象的对象。

  • 类(Class):类是一种抽象数据类型,用来描述具有相同属性和行为的对象的集合。类定义了对象的状态(属性)和行为(方法),是对象的模板或蓝图。在Java中,类由属性(成员变量)和方法(成员函数)组成。

  • 对象(Object):对象是类的实例,是具体存在的、具有特定状态和行为的实体。可以将类看作是对象的模板,而对象是类的实际实例化。

因此,类是描述对象的模板,而对象是类的具体实例。类是对对象进行抽象和定义的,而对象是类的具体化和实例化的结果。在面向对象编程中,通过定义类来创建对象,从而实现对现实世界中事物的抽象和建模。


2. 第一个Java程序

下面看一个简单的 Java 程序,它将输出字符串 Hello World

实例


public class HelloWorld { /* 第一个Java程序 * 它将输出字符串 Hello World */ 
	public static void main(String[] args) {
	System.out.println("Hello World"); // 输出 Hello World 
	} 
}

这是一个简单的 Java 程序,它包含一个名为 HelloWorld 的类,其中包含一个名为 main 的方法。让我们逐步分析这个程序:

  1. 类声明:程序从 public class HelloWorld { 开始。这行代码定义了一个名为 HelloWorld 的公共类。

  2. 注释:在类声明之后,有一段注释 /* 第一个Java程序 * 它将输出字符串 Hello World */。这是一个多行注释,用于描述程序的作用。

  3. main 方法:在类的内部,定义了一个名为 main 的方法。这是 Java 程序的入口点,程序从这里开始执行。方法的声明是 public static void main(String[] args)

    • public 表示该方法是公共的,可以被其他类访问。
    • static 表示该方法是静态的,可以直接通过类名调用,而不需要创建类的实例。
    • void 表示该方法没有返回值。
    • main 是方法的名称。
    • (String[] args) 是方法的参数列表,它接受一个字符串数组作为参数。这个数组用于接收命令行参数。
  4. 输出语句:在 main 方法中,有一行代码 System.out.println("Hello World");。这是一个输出语句,用于在控制台打印字符串 “Hello World”。

  5. 花括号:在 Java 中,代码块使用花括号 {} 来定义。在这个程序中,类的定义和方法的定义都被花括号包裹起来。


参数 String[] args 在 Java 中通常用于接收命令行参数。在执行 Java 程序时,你可以通过命令行输入参数,这些参数会传递给程序,并存储在 args 数组中。

为什么是 String[] 类型呢?

  1. 命令行参数是字符串:在命令行中输入的参数通常是字符串形式的。例如,你可以在命令行中输入 java HelloWorld arg1 arg2,其中 arg1arg2 就是字符串类型的参数。

  2. 数组用于存储多个参数args 参数是一个字符串数组,它可以存储多个参数。每个参数都被存储在数组的一个元素中。例如,args[0] 存储第一个参数,args[1] 存储第二个参数,依此类推。

  3. 灵活性:通过命令行参数,可以在执行程序时动态地传递不同的参数值,从而实现程序的灵活性和通用性。这使得程序可以根据不同的需求执行不同的操作。

因此,String[] args 参数在 Java 中用于接收命令行输入的参数,以便程序根据这些参数执行相应的操作。


参数为什么要 为 String[] args
在Java中,main函数的参数为String类型的数组String[] args是为了接收命令行参数(command-line arguments)。这是为了使Java程序能够与命令行交互,从而实现程序的灵活性和通用性。

通过命令行参数,可以在执行程序时动态地传递不同的参数值,从而实现程序的灵活性和通用性。例如,你可以在命令行中输入java YourProgram arg1 arg2,其中arg1arg2就是传递给程序的参数,它们会被存储在args数组中。程序可以根据这些参数执行相应的操作,从而实现不同的功能。

因此,main函数的参数为String类型的数组是为了接收命令行输入的参数,以便程序根据这些参数执行相应的操作。


整个程序的功能很简单,就是在控制台输出 “Hello World”。这是一个经典的入门示例,用于展示 Java 程序的基本结构和语法。

运行实例 »

下面将逐步介绍如何保存、编译以及运行这个程序:

  • 打开代码编辑器,把上面的代码添加进去;
  • 把文件名保存为:HelloWorld.java;
  • 打开 cmd 命令窗口,进入目标文件所在的位置,假设是 C:\
  • 在命令行窗口输入 javac HelloWorld.java 按下回车键编译代码。如果代码没有错误,cmd 命令提示符会进入下一行(假设环境变量都设置好了)。
  • 再键输入 java HelloWorld 按下回车键就可以运行程序了

你将会在窗口看到 Hello World

$ javac HelloWorld.java
$ java HelloWorld 
Hello World

如果遇到编码问题,我们可以使用 -encoding 选项设置 utf-8 来编译:

javac -encoding UTF-8 HelloWorld.java 
java HelloWorld 

Gif 图演示:


3. 基本语法

编写 Java 程序时,应注意以下几点:

  • 大小写敏感:Java 是大小写敏感的,这就意味着标识符 Hello 与 hello 是不同的。
  • 类名:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 MyFirstJavaClass
  • 方法名所有的方法名都应该以小写字母开头。如果方法名含有若干单词,则后面的每个单词首字母大写。
  • 源文件名源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记 Java 是大小写敏感的),文件名的后缀为 .java。(如果文件名和类名不相同则会导致编译错误)。
  • 主方法入口:所有的 Java 程序由 public static void main(String[] args) 方法开始执行。

4. Java 标识符

Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。

关于 Java 标识符,有以下几点需要注意:

  • 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始
  • 首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合
  • 关键字不能用作标识符
  • 标识符是大小写敏感的
  • 合法标识符举例:age、$salary、_value、__1_value
  • 非法标识符举例:123abc、-salary

5. Java修饰符

像其他语言一样,Java可以使用修饰符来修饰类中方法和属性。主要有两类修饰符:

  • 访问控制修饰符 : default, public , protected, private
  • 非访问控制修饰符 : final, abstract, static, synchronized

在后面的章节中我们会深入讨论 Java 修饰符。


6. Java 变量

Java 中主要有如下几种类型的变量

  • 局部变量
  • 类变量(静态变量)
  • 成员变量(非静态变量)

是的,Java中主要有以下几种类型的变量:

  1. 局部变量:局部变量是定义在方法、构造函数或语句块中的变量,它们只在其所属的方法、构造函数或语句块中可见。局部变量必须在声明后才能使用,并且在方法、构造函数或语句块执行完毕后会被销毁。

  2. 类变量(静态变量):类变量,也称为静态变量,是用static关键字修饰的变量,它们属于类而不是任何单个的实例。类变量在整个类加载过程中只会被初始化一次,并且所有类的实例共享同一个类变量的值。

  3. 成员变量(非静态变量):成员变量,也称为实例变量或非静态变量,是定义在类中但在方法之外的变量。每个类的实例都有自己的一组成员变量的副本,它们与特定实例相关联,每个实例都有自己的成员变量的值。


局部变量 类变量(静态变量) 成员变量(非静态变量)
代码表现

好的,让我用代码示例来说明这些概念:

  1. 局部变量:定义在方法内部的变量,在方法执行时创建,在方法执行结束后销毁。
public class Example {
    public void method() {
        int x = 10; // x是一个局部变量,只在method方法中可见
        System.out.println(x);
    }
}
  1. 类变量(静态变量):使用static关键字修饰的变量,属于类而不是特定的实例,所有实例共享同一个类变量的值。
public class Example {
    public static int count = 0; // count是一个类变量,所有实例共享同一个count的值

    public Example() {
        count++; // 每次创建实例时,count增加1
    }
}
  1. 成员变量(非静态变量):定义在类中但在方法之外的变量,每个实例都有自己的一组成员变量的副本。
public class Example {
    private int x; // x是一个成员变量,每个实例都有自己的x值

    public void setX(int x) {
        this.x = x; // 设置实例的x值
    }

    public int getX() {
        return x; // 获取实例的x值
    }
}

这些示例展示了局部变量、类变量和成员变量的特点和用法,希望能帮助你更好地理解它们之间的区别。

内存存储方式

在底层内存存储上,这三种类型的变量确实有一些区别:

  1. 局部变量局部变量通常存储在栈内存中。栈内存用于存储局部变量和方法调用的信息。当方法被调用时,栈帧被创建,包括局部变量的内存空间。当方法执行完成时,栈帧被销毁,局部变量的内存空间也随之释放。

  2. 类变量(静态变量)类变量存储在方法区(JVM规范中称为永久代元空间)中。方法区用于存储类的结构信息、常量、静态变量等。类加载时,静态变量被分配在方法区中,它们在整个程序的生命周期内都存在,并且所有实例共享同一个静态变量的值。

  3. 成员变量(非静态变量)成员变量存储在堆内存中。堆内存用于存储对象实例及其成员变量。每个对象实例都有自己的一份成员变量的副本,存储在堆内存中。当对象实例被销毁时,其成员变量的内存空间也会被释放。

因此,这三种类型的变量在底层内存存储上有一些区别,主要是存储位置和生命周期的不同。


永久代(Permanent Generation)和元空间(Metaspace)1

在Java虚拟机中,永久代(Permanent Generation)和元空间(Metaspace)是两个不同的概念,它们分别用于存储类的结构信息、常量池、静态变量等。这两个概念存在于不同版本的Java虚拟机中,而且在Java 8及以后的版本中,永久代已经被元空间所取代。

具体来说:

  1. 永久代(Permanent Generation):永久代是Java虚拟机内存模型中的一个区域,主要用于存储类的结构信息、常量池、静态变量等。在Java 7及以前的版本中,永久代的大小是有限的,并且容易出现内存溢出的情况。因此,为了解决永久代内存溢出的问题,在Java 8中被元空间所取代。

  2. 元空间(Metaspace):元空间是Java虚拟机内存模型中的一个区域,用于存储类的结构信息、常量池、静态变量等。与永久代不同的是,元空间不再使用JVM堆内存,而是直接使用本地内存。这样可以避**免永久代内存溢出的问题,并且具有更高的灵活性和性能。****
    **
    总之,永久代和元空间都是用于存储类的结构信息等内容的内存区域,但它们存在于不同的Java虚拟机版本中,并且在内部实现和使用上有一些不同。


堆内存(Heap Memory) 栈内存(Stack Memory)和本地内存(Native Memory)

理解内存管理的概念确实很重要。让我详细介绍一下堆内存、栈内存和本地内存的区别:

  1. 堆内存(Heap Memory)

    • 堆内存是Java虚拟机用于存储对象实例的内存区域。
    • 所有通过new关键字创建的对象都存储在堆内存中。
    • 堆内存由Java虚拟机动态分配和管理,它的大小可以通过启动参数来指定,也可以根据需要动态调整。
    • 堆内存的特点是具有自动内存管理机制(垃圾回收),用于管理对象的创建、使用和销毁。
  2. 栈内存(Stack Memory)

    • 栈内存是用于存储方法调用和局部变量的内存区域。
    • 每个线程都有自己的栈内存,用于存储方法的调用栈和局部变量。
    • 方法调用时,会在栈内存中创建一个栈帧(Stack Frame),用于存储方法的参数、局部变量和方法返回值等信息。
    • 栈内存是由Java虚拟机动态分配和释放的,方法的调用结束后,相应的栈帧会被销毁。
  3. 本地内存(Native Memory)

    • 本地内存是指操作系统提供的一块内存区域,不受Java虚拟机的管理,而是由操作系统直接分配和管理
    • 本地内存通常用于存储本地方法栈、本地方法库、JNI(Java Native Interface)方法等内容。
    • 本地内存的特点是不受Java虚拟机的控制,可以直接通过操作系统提供的API来进行内存操作,但也因此需要开发人员自行负责内存的管理和释放。

简而言之,堆内存是Java虚拟机用于存储对象实例的内存区域,栈内存是用于存储方法调用和局部变量的内存区域,而本地内存是操作系统提供的一块内存区域,用于存储本地方法栈、本地方法库等内容。三者在使用和管理上有着不同的特点和机制。


永久代(Permanent Generation)和元空间(Metaspace)2

永久代(Permanent Generation)是Java虚拟机内存模型中的一个特殊区域,它并不是Java堆内存的一部分,而是一个独立的内存空间,专门用于存储类的结构信息、常量池、静态变量等内容。永久代的创建旨在优化Java虚拟机中的内存管理和类加载机制,提高内存管理的效率和性能。

在Java 7及以前的版本中,永久代是用来存储这些内容的主要内存区域。然而,在Java 8及以后的版本中,由于永久代存在一些问题,特别是容易导致内存溢出的情况,因此被元空间所取代。

元空间(Metaspace)是Java虚拟机内存模型中的另一个特殊区域,用于存储类的结构信息、常量池、静态变量等内容。与永久代不同的是,元空间不再使用Java堆内存,而是直接使用本地内存(Native Memory)。这样可以避免永久代内存溢出的问题,并且具有更高的灵活性和性能。

总之,永久代和元空间都是用于存储类的结构信息等内容的内存区域,但它们存在于不同的Java虚拟机版本中,并且在内部实现和使用上有一些不同。元空间在Java 8及以后的版本中取代了永久代,并且具有更高的灵活性和性能。


JVM 内存空间介绍
1. 程序计数器(Program Counter)
  • 概念:
    • 程序计数器是当前线程执行的字节码指令地址的指示器。
    • 每个线程都有自己的程序计数器。
  • 功能:
    • 确定线程执行的位置,指示下一条要执行的指令。
    • 在多线程环境下,确保线程切换后能够正确恢复执行位置。
  • 存储方式:
    • 程序计数器通常以寄存器的形式存在于CPU中,用于记录当前线程执行的位置。
  • 举例:
    • 在执行Java方法时,程序计数器会指示当前执行的方法字节码指令地址。
2. Java虚拟机栈(Java Virtual Machine Stack)
  • 概念:
    • Java虚拟机栈用于存储方法的调用和局部变量等信息。
    • 每个线程都有自己的Java虚拟机栈。
  • 功能:
    • 管理方法调用的内存和执行过程中的局部变量。
    • 保证方法调用的安全性和正确性。
  • 存储方式:
    • 每个方法调用在虚拟机栈中创建一个栈帧,用于存储方法的局部变量、操作数栈、动态链接、方法出口等信息。
  • 举例:
    • 在执行Java方法时,会根据方法调用情况在虚拟机栈中创建相应的栈帧来存储方法信息。
3. 堆(Heap)
  • 概念:
    • 堆是Java虚拟机中用于存储对象实例和数组等动态分配数据的内存区域。
    • 是所有线程共享的内存区域。
  • 功能:
    • 提供内存给Java对象实例和数组使用。
    • 动态分配内存,允许对象的动态创建和销毁。
  • 存储方式:
    • 由垃圾收集器管理的动态分配的内存块。
  • 举例:
    • 存储new关键字创建的对象和数组。
4. 方法区(Method Area)
  • 概念:
    • 方法区用于存储类的元数据、常量池、静态变量等信息。
    • 是所有线程共享的内存区域。
  • 功能:
    • 存储类相关的元信息和静态变量。
    • 用于运行时常量池的实现。
  • 存储方式:
    • 类加载时分配,可通过反射访问。
  • 举例:
    • 存储类的信息、静态变量和常量池中的常量。
5. 运行时常量池(Runtime Constant Pool)
  • 概念:
    • 每个类都有自己的运行时常量池,用于存储常量和符号引用。
    • 是方法区的一部分。
  • 功能:
    • 存储类中的常量值和符号引用。
    • 提供常量池的动态存储和访问。
  • 存储方式:
    • 类加载时动态生成,可通过反射访问。
  • 举例:
    • 存储字符串常量、类和方法的符号引用。
6. 本地方法栈(Native Method Stack)
  • 概念:
    • 用于存储本地方法(Native Method)的调用信息和数据。
    • 类似于Java虚拟机栈,但用于本地方法的调用。
  • 功能:
    • 执行本地方法。
  • 存储方式:
    • 栈帧形式保存方法调用的信息。
  • 举例:
    • 调用C或C++编写的本地方法。
7. 直接内存(Direct Memory)
  • 概念:
    • 由NIO库提供的一种内存分配方式,允许Java程序直接使用操作系统的内存。
    • 不受Java堆内存的限制。
  • 功能:
    • 提高I/O操作的性能。
  • 存储方式:
    • 直接使用操作系统的内存,通过ByteBuffer来操作。
  • 举例:
    • NIO中的Channel使用直接内存来提高I/O性能。

7. Java 数组

数组基本介绍

数组是储存在堆上的对象,可以保存多个同类型变量。在后面的章节中,我们将会学到如何声明、构造以及初始化一个数组。


数组的特点

在Java中,数组是一种特殊的数据结构,用于存储多个相同类型的元素。与其他对象一样,数组也是储存在堆上的对象。以下是有关Java数组的一些重要特点:

  1. 存储多个同类型变量:数组可以保存多个相同类型的元素,这些元素可以是基本数据类型(如int、double等)或对象类型(如String、自定义类等)
    Ps: 是的,Java数组是同一种类型的元素的有序集合,因此只能存储相同类型的变量。换句话说,数组中的元素必须是同一种数据类型,例如整数、浮点数、字符串等。试图将不同类型的变量存储在同一个数组中会导致编译错误。这种严格的类型要求是Java语言的特性之一,有助于提高代码的可靠性和安全性。

  2. 声明数组:在Java中,声明数组需要指定数组的类型和名称,例如:int[] myArray;声明了一个整型数组变量myArray

  3. 构造数组:在声明数组后,需要通过new关键字分配内存空间并创建数组对象,例如:myArray = new int[5];创建了一个包含5个整数元素的整型数组对象。

  4. 初始化数组:数组可以在声明时或者之后进行初始化。在声明时初始化数组,可以直接指定初始值,如:int[]例 myArray = {1, 2, 3, 4, 5};在之后进行初始化,则需要通过索引逐个为数组元素赋值。

总的来说,Java数组是一种便捷的数据结构,用于存储多个同类型的元素。通过声明、构造和初始化数组,我们可以方便地操作和处理多个数据。


数据类型的赋值方式小总结

好的,让我为您介绍Java中常见的数据类型的赋值方式:

  1. 基本数据类型:

    • 直接赋值:直接将数值赋给变量。
      int num = 10; // 直接赋值
      
    • 初始化列表赋值:在声明变量时,使用等号和数值进行赋值。
      int num = new int(10); // 初始化列表赋值
      
    • 用户输入赋值:通过用户输入的方式给变量赋值。
      Scanner scanner = new Scanner(System.in);
      int num = scanner.nextInt(); // 用户输入赋值
      
    • 计算赋值:通过计算得到的结果给变量赋值。
      int a = 5;
      int b = 10;
      int result = a + b; // 计算赋值
      
  2. 引用数据类型(对象类型):

    • 直接赋值:直接将对象赋给引用变量。
      String str = "Hello"; // 直接赋值
      
    • 初始化列表赋值:在声明引用变量时,使用等号和对象进行赋值。
      String str = new String("Hello"); // 初始化列表赋值
      
    • 用户输入赋值:通过用户输入的方式给引用变量赋值。
      Scanner scanner = new Scanner(System.in);
      String str = scanner.nextLine(); // 用户输入赋值
      
    • 方法返回值赋值:通过方法返回的结果给引用变量赋值。
      String str = getHello(); // 方法返回值赋值
      
  3. 数组类型:

    • 直接赋值:直接在声明数组时初始化数组元素。
      int[] arr = {1, 2, 3}; // 直接赋值
      
    • 初始化列表赋值:在声明数组时使用大括号括起来的列表进行赋值。
      int[] arr = new int[]{1, 2, 3}; // 初始化列表赋值
      
    • 索引赋值:通过循环结构逐个访问数组中的元素,并为每个元素赋予特定的值。
      int[] arr = new int[5];
      for (int i = 0; i < arr.length; i++) {
          arr[i] = i * 2; // 索引赋值
      }
      

这些是Java中常见的数据类型的赋值方式,根据具体的场景和需求选择最适合的方式来进行赋值操作。

更多的赋值方式:

  1. 枚举类型(Enum):

    • 直接赋值:直接将枚举常量赋给枚举变量。
    enum Day { MONDAY, TUESDAY, WEDNESDAY }
    Day today = Day.MONDAY; // 直接赋值
    
    • 枚举索引赋值:通过枚举常量的索引值给枚举变量赋值。
    Day today = Day.values()[0]; // 枚举索引赋值
    
    • 枚举方法赋值:通过调用枚举常量的方法返回结果给枚举变量赋值。
    Day today = Day.valueOf("MONDAY"); // 枚举方法赋值
    
  2. 泛型类型(Generic):

    • 直接赋值:直接使用泛型对象进行赋值。
    List<String> list = new ArrayList<>(); // 直接赋值
    
    • 泛型方法赋值:通过调用泛型方法返回结果给泛型变量赋值。
    List<String> list = Collections.emptyList(); // 泛型方法赋值
    
    • 泛型通配符赋值:通过使用通配符的方式赋值。
    List<?> list = new ArrayList<>(); // 泛型通配符赋值
    
  3. 自定义类(Class):

    • 初始化列表赋值:在声明对象变量时,使用等号和new关键字创建对象进行赋值。
    MyClass obj = new MyClass(); // 初始化列表赋值
    
    • 构造方法赋值:通过调用对象的构造方法来创建对象并赋值。
    MyClass obj = new MyClass("parameter"); // 构造方法赋值
    
    • 对象方法赋值:通过调用对象的方法返回结果给对象变量赋值。
    MyClass obj = getMyClass(); // 对象方法赋值
    

数据类型分类

数据类型可以分为两大类:基本数据类型(Primitive Data Types)和引用数据类型(Reference Data Types)。

  1. 基本数据类型:

    • 整型(Integral Types):用于表示整数,包括byte、short、int、long四种类型。
      • byte:1字节,范围为-128到127。
      • short:2字节,范围为-32,768到32,767。
      • int:4字节,范围为-231到231-1。
      • long:8字节,范围为-263到263-1。
    • 浮点型(Floating-Point Types):用于表示带小数部分的数字,包括float和double两种类型。
      • float:4字节,范围为IEEE 754格式的单精度浮点数。
      • double:8字节,范围为IEEE 754格式的双精度浮点数。
    • 字符型(Character Type):用于表示单个字符,char类型,占2字节。
    • 布尔型(Boolean Type):用于表示逻辑值,boolean类型,只有两个值:true和false。
  2. 引用数据类型:

    • 类型(Class Type):用于表示自定义的对象,包括类、接口、数组等。
    • 接口类型(Interface Type):用于表示接口。
    • 数组类型(Array Type):用于表示数组对象。

基本数据类型是存储基本数值的类型,而引用数据类型是存储对象引用的类型。在Java中,基本数据类型的变量直接存储数值,而引用数据类型的变量存储的是对象的引用,实际的对象数据存储在堆内存中。

引用数据类型详解

当我们谈论引用数据类型时,我们实际上是在谈论对象的引用,而不是对象本身。引用数据类型在Java中用于表示对象的引用或地址而不是对象本身的实际数据。

  1. 类类型(Class Type):

    • 类是一种用户自定义的数据类型,它可以包含属性(字段)和方法。
    • 通过类可以创建多个对象,每个对象都有自己的属性和方法。
    • 类型本身并不存储数据,而是定义了对象的结构和行为。
    • 例如:
      class MyClass {
          int x;
          void myMethod() {
              System.out.println("Hello from MyClass");
          }
      }
      
  2. 接口类型(Interface Type):

    • 接口是一种抽象的数据类型,它定义了一组方法的签名,但没有方法的具体实现。
    • 类可以实现一个或多个接口,从而获得接口定义的方法。
    • 接口用于实现多态性和规范类的行为。
    • 例如:
      interface MyInterface {
          void myMethod();
      }
      
  3. 数组类型(Array Type):

    • 数组是一种特殊的引用数据类型,它用于存储多个相同类型的元素。
    • 数组可以是基本数据类型的数组,也可以是引用数据类型的数组。
    • 数组的长度是固定的,一旦创建后无法改变。
    • 例如:
      int[] numbers = new int[5];
      String[] names = new String[3];
      

引用数据类型的变量存储的是对象的地址或引用,而不是对象本身的数据。当我们创建一个对象时,实际上是在堆内存中分配了内存空间,并返回了对象的引用,然后将这个引用赋给引用数据类型的变量。这样,变量就可以通过引用访问对象的属性和方法。


8. Java 枚举

Java 5.0引入了枚举,枚举限制变量只能是预先设定好的值。使用枚举可以减少代码中的 bug。

例如,我们为果汁店设计一个程序,它将限制果汁为小杯、中杯、大杯。这就意味着它不允许顾客点除了这三种尺寸外的果汁。

实例

class FreshJuice {
    // 定义一个枚举类型表示果汁的大小
    enum FreshJuiceSize { 
        SMALL, // 小杯
        MEDIUM, // 中杯
        LARGE // 大杯
    }
    // 声明一个枚举类型的变量表示果汁的大小
    FreshJuiceSize size;
}

public class FreshJuiceTest {
    public static void main(String[] args) {
        // 创建一个FreshJuice对象
        FreshJuice juice = new FreshJuice();
        // 为对象的size属性赋值为MEDIUM,表示中杯大小
        juice.size = FreshJuice.FreshJuiceSize.MEDIUM;
    }
}

**注意:**枚举可以单独声明或者声明在类里面。方法、变量、构造函数也可以在枚举中定义。


如何修改枚举类型的值

枚举类型中的值通常是在定义时确定的,并且在程序运行时是不可更改的。但是,如果你需要修改枚举类型中的值,你可以按照以下步骤来实现:

  1. 修改枚举类型的定义:你可以直接修改枚举类型的定义,更改已有枚举常量的值或者添加新的枚举常量。
enum Weekday {
    MONDAY,    // 星期一
    TUESDAY,   // 星期二
    WEDNESDAY, // 星期三
    THURSDAY,  // 星期四
    FRIDAY    // 星期五
}
  1. 编译并重新运行程序:在修改了枚举类型的定义后,需要重新编译并运行程序,以使修改生效。
public class Main {
    public static void main(String[] args) {
        Weekday today = Weekday.WEDNESDAY;
        System.out.println("Today is " + today);
    }
}

在这个例子中,如果你希望将 WEDNESDAY 修改为 WEEKEND,你可以将枚举类型的定义修改为:

enum Weekday {
    MONDAY,    // 星期一
    TUESDAY,   // 星期二
    WEEKEND,   // 周末
    THURSDAY,  // 星期四
    FRIDAY    // 星期五
}

然后重新编译并运行程序,今天的值将会被更新为 WEEKEND。


9. Java 关键字

下面列出了 Java 关键字。这些保留字不能用于常量、变量、和任何标识符的名称。

类别关键字说明
访问控制private私有的
protected受保护的
public公共的
default默认
类、方法和变量修饰符abstract声明抽象
class
extends扩充、继承
final最终值、不可改变的
implements实现(接口)
interface接口
native本地、原生方法(非 Java 实现)
new创建
static静态
strictfp严格浮点、精准浮点
synchronized线程、同步
transient短暂
volatile易失
程序控制语句break跳出循环
case定义一个值以供 switch 选择
continue继续
do运行
else否则
for循环
if如果
instanceof实例
return返回
switch根据值选择执行
while循环
错误处理assert断言表达式是否为真
catch捕捉异常
finally有没有异常都执行
throw抛出一个异常对象
throws声明一个异常可能被抛出
try捕获异常
包相关import引入
package
基本类型boolean布尔型
byte字节型
char字符型
double双精度浮点
float单精度浮点
int整型
long长整型
short短整型
变量引用super父类、超类
this本类
void无返回值
保留关键字goto是关键字,但不能使用
const是关键字,但不能使用
**注意:**Java 的 null 不是关键字,类似于 true 和 false,它是一个字面常量,不允许作为标识符使用。

10. Java注释

类似于 C/C++、Java 也支持单行以及多行注释。

注释中的字符将被 Java 编译器忽略。

public class HelloWorld {
   /* 这是第一个Java程序
    * 它将输出 Hello World
    * 这是一个多行注释的示例
    */
    public static void main(String[] args){
       // 这是单行注释的示例
       /* 这个也是单行注释的示例 */
       System.out.println("Hello World"); 
    }
}

更多内容可以参考:Java 注释


Java 注释总结

Java 支持多种注释方式,主要包括单行注释、多行注释和文档注释。

  1. 单行注释: 使用//来表示,从//开始到行末都被注释掉。

    // 这是单行注释
    int x = 10; // 这是另一个单行注释
    
  2. 多行注释: 使用/*开头和*/结尾,中间的内容都被注释掉。

    /*
     * 这是多行注释
     * 可以跨越多行
     */
    int y = 20; /* 这是另一个多行注释 */
    
  3. 文档注释: 用于生成代码文档,通常在类、方法、字段的前面使用/** ... */形式的注释。

    /**
     * 这是文档注释
     * 用于生成代码文档
     */
    public class MyClass {
        /**
         * 这是一个方法
         * @param x 参数 x
         * @return 返回值
         */
        public int myMethod(int x) {
            return x * x;
        }
    }
    

文档注释通常包含对代码的详细描述,以及使用@param@return等标签来指定方法的参数和返回值的含义。


11. Java 空行

空白行或者有注释的行,Java 编译器都会忽略掉。


12. 继承

在 Java 中,一个类可以由其他类派生。如果你要创建一个类,而且已经存在一个类具有你所需要的属性或方法,那么你可以将新创建的类继承该类。

利用继承的方法,可以重用已存在类的方法和属性,而不用重写这些代码。被继承的类称为超类(super class),派生类称为子类(sub class)。


理解继承的全部概念需要掌握以下内容:

  1. 父类和子类:

    • 父类是被继承的类,子类是继承父类的类。
    • 子类**继承了父类的属性和方法,并且可以添加新的属性和方法。****
  2. extends关键字:

    • 使用extends关键字声明一个类继承另一个类。
    • 子类可以继承父类的非私有属性和方法。
  3. 单继承:

    • Java不支持多继承,一个类只能继承一个直接父类。
  4. 重写(Override):

    • 子类可以重写父类的方法,即在子类中重新实现父类的方法,以满足子类的特定需求。
    • 重写的方法具有相同的名称、参数列表和返回类型。
  5. super关键字:

    • 子类可以使用super关键字调用父类的方法或访问父类的属性。
    • 使用super()调用父类的构造方法。
  6. 构造方法:

    • 子类的构造方法可以调用父类的构造方法来初始化继承的属性。
    • 如果子类没有显式地调用父类的构造方法,则会隐式地调用父类的默认构造方法。
  7. 继承链:

    • 继承可以形成一个继承链,一个类可以作为多个子类的父类,也可以是其他类的子类。
  8. 抽象类和接口:

    • Java中的抽象类和接口提供了更高级别的继承机制,允许定义没有实现的方法,从而使得子类必须实现这些方法。

理解这些概念可以帮助你全面掌握Java中的继承机制,进而更好地设计和编写面向对象的程序。

实例

好的,让我通过一个例子来说明Java的继承机制。

假设我们有一个Vehicle类,表示各种交通工具,其中包括属性brand(品牌)和方法run()(行驶):

class Vehicle {
    String brand;

    public Vehicle(String brand) {
        this.brand = brand;
    }

    public void run() {
        System.out.println(brand + " is running.");
    }
}

现在,我们要创建一个子类Car来表示汽车,汽车除了继承父类的属性和方法外,还有自己独特的属性numOfSeats(座位数):

class Car extends Vehicle {
    int numOfSeats;

    public Car(String brand, int numOfSeats) {
        super(brand); // 调用父类的构造方法来初始化brand属性
        this.numOfSeats = numOfSeats;
    }

    // 方法重写,重写父类的run方法
    @Override
    public void run() {
        System.out.println(brand + " car with " + numOfSeats + " seats is running.");
    }

    // Car类的特有方法
    public void honk() {
        System.out.println("Honk honk!");
    }
}

现在,我们来使用这些类:

public class Main {
    public static void main(String[] args) {
        // 创建一个汽车对象
        Car myCar = new Car("Toyota", 5);
        
        // 调用继承自父类的方法
        myCar.run(); // 输出:Toyota car with 5 seats is running.

        // 调用子类自己的方法
        myCar.honk(); // 输出:Honk honk!
    }
}

在这个例子中,Car类继承了Vehicle类的属性brand和方法run(),并添加了自己的属性numOfSeats和方法honk()。通过调用父类的构造方法super(brand)来初始化父类的属性,通过@Override注解重写父类的run()方法,以实现子类特有的功能。


13. 接口

在 Java 中,接口可理解为对象间相互通信的协议。接口在继承中扮演着很重要的角色。

接口只定义派生要用到的方法,但是方法的具体实现完全取决于派生类。


接口是Java编程中的一种重要概念,它定义了一组抽象方法的集合,但没有具体的实现。下面是关于接口的一些详细信息:

  1. 定义: 接口使用 interface 关键字定义,其中包含一组抽象方法的声明,这些方法通常没有具体的实现。

  2. 抽象方法: 接口中的方法通常是抽象的,不包含方法体。这些方法只有方法签名,没有具体的实现逻辑。

  3. 特性:

    • 接口中的方法默认为 public abstract,可以省略这些修饰符。
    • 接口中可以包含常量(public static final修饰的变量),这些常量默认为 public static final
    • 接口不能包含实例变量。
    • 一个类可以实现多个接口。
  4. 实现接口: 类实现接口时,需要使用 implements 关键字,并提供接口中所有抽象方法的具体实现。

  5. 多态性: 接口的一个重要作用是实现多态性。通过接口,可以将不同类的对象视为同一类型,从而实现针对接口编程。

  6. 扩展性: 接口提供了一种灵活的方式来设计和扩展类的行为,通过实现不同的接口,可以实现不同的功能组合。

  7. 使用场景:

    • 接口用于定义类之间的契约关系,实现了相同接口的类必须提供相同的行为。
    • 接口用于实现回调函数,允许对象在某些事件发生时通知其他对象。
    • 接口用于实现多继承,因为Java类不支持多继承,但是一个类可以实现多个接口。

总的来说,接口提供了一种规范和契约,用于定义类之间的通信和行为,从而增强了代码的灵活性、可维护性和可扩展性。


14. Java 源程序与编译型运行区别

如下图所示:

下一节介绍 Java 编程中的类和对象。之后你将会对 Java 中的类和对象有更清楚的认识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值