Java入门

Java 介绍

开始学习Java

Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言,目前由Oracle拥有。

Java 可运行于多个平台,如Windows, Mac OS,及其他多种UNIX版本的系统。

Java 是平台无关的语言,用Java编写的应用程序不用修改就可以在不同的平台上运行。
Java 实现了 “一次编写,到处运行” 的机制。

Java 介绍

Java 无处不在,据估计,全球范围内有超过30亿台设备运行Java。

Java 具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点,能够适应几乎任何类型的应用程序的需求。

Java 被用于为谷歌的Android操作系统的应用程序,各种桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。

第一个Java程序

编写第一个Java程序

编写一个简单的Java程序,它将在屏幕上打印“Hello World”。

public class Main {
  public static void main(String[] args) {
    System.out.print("Hello World");
  }
}

在上面的例子中,我们命名了类 Main。您将在后面的章节中了解更多关于类的知识。

在Java中,每个应用程序都有一个入口点或一个起点,这是一个名为main的方法。


提示:
(1)每个Java程序都必须包含一个类。
(2)每个Java程序都从main方法开始。


main方法

在Java中,main方法必须采用此方法签名:
image

public static void main(String[] args)

访问修饰符 public: 表示任何人都可以访问它
静态修饰符 static: 表示该方法可以在不创建包含main方法的类的实例的情况下运行
返回值类型 void : 表示该方法不会返回任何值
方法名 main: main是主方法的默认方法名


提示:方法的参数在方法名称后面的括号内声明,对于main来说,这是一个名为args的字符串数组。


System.out.println()

下面是main()方法的主体,用花括号括起来:
image
主体部分:

{
  System.out.println("Hello World!");
}

println 方法在屏幕上打印一行文本。

System 类及其输出流用于访问println方法。


提示:在类,方法和其他流控制结构中,代码总是用花括号括起来{}。


java中的分号

您可以将不同的文本作为参数传递给println方法来进行打印。

public class Main {
  public static void main(String[] args) {
    System.out.println("I am learning Java");
  }
}

在Java中,每个代码语句必须以分号结尾。但记住,不要在使用花括号定义的主体后面的方法类声明之后使用分号。
image
image

Java基本语法

Java基本语法

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

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


提示:切记Java是大小写敏感的,Java文件名和类名如果不相同则会导致编译错误。


Java标识符

在Java中,类名、变量名以及方法名都被称为标识符。关于Java标识符,我们应该注意以下几点:

标识符由字母、美元符、下划线或数字组成。
标识符应以字母、美元符、下划线开始。
Java标识符是大小写敏感的,长度无限制。
不能使用关键字作为Java标识符,关键字如class、void等等。
下面是标识符举例:
image

Java关键字

Java关键字是对Java编译器有特殊含义的字符串,是编译器和程序员的一个约定,程序员利用关键字来告诉编译器其声明的变量类型、类、方法特性等信息。Java语言共定义了如下所示的关键字。

关键字 含义 类型 备注
abstract 表明类或者成员方法具有抽象属性 定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象 public abstract class C(){} 介于类与接口中间,可以有也可以没有已经实现的方法体
assert 断言,用来进行程序调试
boolean 基本数据类型之一,声明布尔类型的关键字 数据类型的关键字 --
break 提前跳出一个块 条件循环
byte 基本数据类型之一,字节类型 数据类型的关键字 8bit
case 用在switch语句之中,表示其中的一个分支 条件循环
catch 用在异常处理中,用来捕捉异常 错误处理 1.try+catch程序的流程是:运行到try块中,如果有异常抛出,则转到catch块去处理。然后执行catch块后面的语句2.try+catch+finally程序的流程是:运行到try块中,如果有异常抛出,则转到catch块,catch块执行完毕后,执行finally块的代码,再执行finally块后面的代码。如果没有异常抛出,执行完try块,也要去执行finally块的代码。然后执行finally块后面的语句3.try+finally程序的流程是:运行到try块中,如果有异常抛出的话,程序转向执行finally块的代码。那末finally块后面的代码还会被执行吗?不会!因为你没有处理异常,所以遇到异常后,执行完finally后,方法就已抛出异常的方式退出了。这种方式中要注意的是,由于你没有捕获异常,所以要在方法后面声明抛出异常
char 基本数据类型之一,字符类型 数据类型的关键字 16bit
class 声明一个类 定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象 public class A(){} 花括号里有已实现方法体,类名需要与文件名相同
const 保留关键字,没有具体含义
continue 回到一个块的开始处 条件循环 中断本次循环,并并开始下一次
default 默认,例如,用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现 条件循环
do 用在do-while循环结构中 条件循环 常与while连用
double 基本数据类型之一,双精度浮点数类型 数据类型的关键字 64bit
else 用在条件语句中,表明当条件不成立时的分支 条件循环 常与if连用,用法相同
enum 枚举 声明一个类
extends 表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口 定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象 用于类继承类 public class A extends D(){}
false 数据类型的关键字
final 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量 修饰方法、类、属性和变量 方法和类都可以用final来修饰。final修饰的类是不能被继承的。final修饰的方法是不能被子类重写。常量的定义:final修饰的属性就是常量。
finally 用于处理异常情况,用来声明一个基本肯定会被执行到的语句块 错误处理
float 基本数据类型之一,单精度浮点数类型 数据类型的关键字 32bit
for 一种循环结构的引导词 条件循环 for ( ; ; ){}
goto 保留关键字,没有具体含义
if 条件语句的引导词 条件循环 if(){} 如果小括号里面怎么怎么样 花括号就怎么怎么样
implements 表明一个类实现了给定的接口 定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象 定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象
import 表明要访问指定的类或包 包的关键字 当使用某个包的一些类时,仅需类名 然后使用ctrl+shift+o或者选定类名(类或属性或方法)按住ctrl+单击 即可自动插入类所在的包。如:JFrame 快捷键之后自动加入import javax.swing.JFrame;
instanceof 用来测试一个对象是否是指定类型的实例对象 条件循环 一个二元操作符,和==,>,<是同一类的。测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据
int 基本数据类型之一,整数类型 数据类型的关键字 32bit
interface 接口 定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象 public interface B(){} 花括号里有方法体,但没有实现,方法体句子后面是英文分号“:”结尾
long 基本数据类型之一,长整数类型 数据类型的关键字 64bit
native 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的 修饰方法、类、属性和变量
null 空值 数据类型的关键字
new 用来创建新实例对象 定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象 A a=new A(); A表示一个类
package 包的关键字 将所有有关的类放在一个包类以便查找修改等。如:**package **javake.flycat.draw002;
private 一种访问控制方式:私用模式 访问修饰符的关键字 当前类可用
protected 一种访问控制方式:保护模式 访问修饰符的关键字 当前包内可用
public 一种访问控制方式:共用模式 访问修饰符的关键字 可跨包,(默认选择)
return 从成员方法中返回数据 条件循环 return 一个返回值类型
short 基本数据类型之一,短整数类型 数据类型的关键字 16bit
static 表明具有静态属性 修饰方法、类、属性和变量 属性和方法都可以用static修饰,直接使用类名.属性和方法名。 只有内部类可以使用static关键字修饰,调用直接使用类名.内部类类名进行调用。 static可以独立存在。静态块
strictfp 用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范 修饰方法、类、属性和变量
super 表明当前对象的父类型的引用或者父类型的构造方法 修饰方法、类、属性和变量 常见public void paint(Graphics g){super.paint(g); ··· }
switch 分支语句结构的引导词 条件循环 switch(表达式){case 常量表达式1:语句1;....case 常量表达式2:语句2;default:语句;}default就是如果没有符合的case就执行它,default并不是必须的.case后的语句可以不用大括号.switch语句的判断条件可以接受int,byte,char,short,不能接受其他类型.
synchronized 表明一段代码需要同步执行 修饰方法、类、属性和变量
this 指向当前实例对象的引用 修饰方法、类、属性和变量 调用当前类中的方法(表示调用这个方法的对象)this.addActionListener(al):等等
throw 抛出一个异常 错误处理 一些可以导致程序出问题的因素,比如书写错误,逻辑错误或者是api的应用错误等等. 为了防止程序的崩溃就要预先检测这些因素,所以java 使用了异常这个机制.在java中异常是靠 "抛出" 也就是英语的"throw" 来使用的,意思是如果发现到什么异常的时候就把错误信息 "抛出"
throws 声明在当前定义的成员方法中所有需要抛出的异常 错误处理 把异常交给他的上级管理,自己不进行异常处理
transient 声明不用序列化的成员域 修饰方法、类、属性和变量
true 数据类型的关键字
try 尝试一个可能抛出异常的程序块 错误处理
void 声明当前成员方法没有返回值 数据类型的关键字 public void A(){} 其他需要返回的经常与return连用
volatile 表明两个或者多个变量必须同步地发生变化 修饰方法、类、属性和变量
while 用在循环结构中 条件循环 while 怎么样就do什么 while(){}
image

Java注释

java注释

您可以在Java代码中包含注释,这将提高源代码的可读性。
Java 支持单行以及多行注释。注释中的字符将被 Java 编译器忽略。

Java 单行注释以 // 开始,直到行尾为止。例如:

// 这是一个单行注释
x = 10; // 代码后的单行注释

单行注释也能以 /* 开始,以 */为止(该方式后面会讲到也可以用于多行注释)。例如:

/* 这也是一个单行注释 */

提示:在编写代码时添加注释是一种很好的做法,因为当你需要回顾它时,以及其他人可能需要阅读它时,它们提供了解释和理解。


Java多行注释

Java 也支持跨多行的注释。

Java 多行注释以 /* 开始,以 */为止。例如:

/*  这是一个
 *  多行注释 
 */

请注意,Java 不支持嵌套的多行注释,但是,您可以在多行注释中嵌套单行注释。例如:

/* 嵌套单行注释
   // 单行注释
 */

java文档注释

文档注释允许你在程序中嵌入关于程序的信息。你可以使用 javadoc 工具软件来生成信息,并输出到HTML文件中。

文档注释,使你更加方便的记录你的程序信息。

Java 文档注释以 /** 开始,以 */结束。例如:

/** 这是一个文档注释 */

/** 这也是一个
    文档注释 */

在开始的 /** 之后,第一行或几行是关于类、变量和方法的主要描述。

之后,你可以包含一个或多个各种各样的@标签。每一个@标签必须在一个新行的开始或者在一行的开始紧跟星号(*).

下面是一个类的说明注释的实例:

/**
* 这个类演示了文档注释
* @author Ada
* @version 1.0
*/

java变量

变量

什么是变量?变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如: 水杯是容器,用来装载水;衣柜用来装载衣裤;那么变量是装载什么的呢?是数据!所以:变量是内存中装载数据的小盒子,你只能用它来存数据和取数据。

变量被赋予名称(或标识符),例如:name,age,high等。该名称唯一标识每个变量,用来为变量赋值或检索存储的值。

在Java中,变量有各种类型。下面是一些例子:

int:整数,如123和-456。
double:浮点数,可选小数点和小数部分,如3.1416,-11.22。
String:如 “Hello” 或 “Good Morning!” 等文本。文本字符串括在双引号内。

你可以声明一个类型的变量并赋值。例如:

String name = "Lu";

这将创建一个名为String类型的变量,并为其赋值“Lu”。


提示:一个变量与一个类型相关联,并且只能够存储该特定类型的值。


变量

下面是一个变量声明的例子:

class MyJavaClass {
  public static void main(String[] args) {
    String name ="Lu";
    int age = 26;
    double score = 18.9;
    char group = 'B';
  }
}

char是字符类型,用来定义一个字符。
还有一种类型是布尔类型,它只有两个取值:truefalse,这种类型只作为一种标志来记录 true/false 情况。

例如:

boolean online = true;

提示:可以使用逗号隔开声明多个同类型变量。例如:int a = 17, b = 30;


基本运算符

算数运算符

作为一门计算机语言,Java 也提供了一套丰富的运算符来操纵变量。

算术运算符用在数学表达式中,它们的作用和在数学中的作用一样,主要用于进行基本的算术运算,如:加法、减法、乘法、除法等。

下面列出了所有的算术运算符:

+(加法):相加运算符两侧的值,如 A + B。
-(减法):左操作数减去右操作数,如 A - B。
*(乘法):相乘操作符两侧的值,如 A * B。
/(除法):左操作数除以右操作数,如 B / A。
%(取模):左操作数除以右操作数的余数,如 B % A。
++(自增): 操作数的值增加1,如 B++ 或 ++B 。
--(自减):操作数的值减少1,如 B-- 或 --B 。


提示:++ 和 -- 既可以出现在操作数的左边,也可以出现在右边,但结果是不同的。关于自增自减运算符的知识,我们将在后面的内容中进一步介绍。


加法、减法运算符

加法运算符

加法(+) 运算符将运算符两侧的值相加,可以是两个常量,一个常量和一个变量,或一个变量和一个变量。

下面列出了一些例子:

int sum1 = 30 + 20; 
int sum2 = sum1 + 10; 
int sum3 = sum1 + sum2;

减法运算符

减法(-) 运算符从左操作数减去右操作数。

下面列出了一些例子:

int sum1 = 50 - 20;
int sum2 = sum1 - 10;
int sum3 = sum1 - sum2;

乘法、除法运算符

乘法运算符

乘法(*) 运算符将运算符两侧的值相乘。

下面列出了一些例子:

int sum1 = 50 * 2;
int sum2 = sum1 * 10;
int sum3 = sum1 * sum2;

除法运算符

除法(/) 运算符从左操作数除以右操作数。

下面列出了一些例子:

int sum1 = 50 / 5;
int sum2 = sum1 / 2;
int sum3 = sum1 / sum2;

在上面的例子中,我们将 int 用作数据类型,运算符的结果将是整数。如果你需要检索带有小数点的值,你可以使用 double 数据类型。

取模运算符

取模(%) 运算符用来求余数,从左操作数除以右操作数的余数。

下面是一个例子:

int a = 11;
int b = a % 5; // b为1

在上面的例子中,将11除以5得到商为2,余数为1。因此,将值1赋值给b变量。

自增自减运算符

自增(++) 自减(--) 运算符是一种特殊的算术运算符,在算术运算符中需要两个操作数来进行运算,而自增自减运算符是一个操作数。

自增(++) 运算符将操作数的值增加1。下面是一个例子:

int a = 3;
++a; // 自增运算

进行自增运算后的a为4。

自减(--) 运算符将操作数的值减少1。下面是一个例子:

int b = 3;
--b; // 自减运算

进行自减运算后的b为2。

前缀和后缀自增自减

自增和自减运算符都可以使用前缀和后缀两种形式。

前缀自增自减法(++a,--a): 先进行自增或者自减运算,再进行表达式运算。

下面是一个例子:

int a = 5;
int b = ++a;

首先将a加1,a变为6,然后赋值给b,所以a和b的值现在是6。

后缀自增自减法(a++,a--): 先进行表达式运算,再进行自增或者自减运算 。

下面是一个例子:

int a = 5;
int b = a++; 

首先将a赋值给b,然后将a加1,因此a变成6,而b的值是5。

赋值运算符

你可能已经熟悉基本的赋值运算符(=),它将右操作数的值赋给左侧操作数。

例如,在下面的例子中,将值3赋值给一个int类型的a变量。

int a = 3;

Java 支持许多赋值运算符,使编写代码更加容易。下面是一些赋值运算符的介绍。

加和赋值运算符 (+=):

int a1 = 2;
int a2 = 4;
a2 += a1; // 等价于 a2 = a2 + a1;

// 结果a2=6,a1=2

减和赋值运算符(-=):

int a1 = 2;
int a2 = 4;
a2 -= a1; // 等价于 a2 = a2 - a1;

// 结果a2=2,a1=2

同样,Java支持乘和赋值运算符(*=),除和赋值运算符(/=) 以及取模和赋值运算符(%=)。

字符串

创建字符串

字符串广泛应用在 Java 编程中,在 Java 中,字符串是表示字符序列的对象。

Java 提供了 String 类来创建和操作字符串。

创建字符串最简单的方式如下:

String s = "Hello World!"; 

在代码中每遇到一个字符串时,编译器会在这种情况下创建一个String对象,如:"Hello World!"。

连接字符串

在 Java 中,使用 '+' 操作符来连接字符串。

下面是一个例子:

String firstName, lastName;
firstName = "John";
lastName = "Smith";

System.out.println("My name is "+firstName+" "+lastName);
        
// 输出: My name is John Smith

获取用户输入

获取用户输入

Java提供了不同的方式来获取用户输入,使用Scanner对象是最常见的,也是最容易实现用户输入的。

导入Scanner类以便使用Scanner对象,如下所示:

import java.util.Scanner; 

要使用Scanner类,请使用以下语法创建该类的实例:

Scanner myVar = new Scanner(System.in);

您现在可以读取用户输入的各种输入数据。

在Java中,获取输入的字符串,我们可以通过Scanner类的nextLine()next()方法。

下面是用于获取用户输入的程序示例:

import java.util.Scanner;

class MyJavaClass {
  public static void main(String[] args) {
    Scanner myVar = new Scanner(System.in);
    System.out.println(myVar.nextLine());        
  }
}

这将等待用户输入内容并打印该输入。

条件声明

条件语句

条件语句用于根据不同的条件执行不同的操作。

if 语句是最常用的条件语句之一。一个 if 语句包含一个布尔表达式和一条或多条语句。

if 语句的用法如下:

if (布尔表达式) {
   //如果布尔表达式为true将执行的语句
}

如果 if 语句的布尔表达式的值为 true,则执行 if 语句内的代码块,否则执行 if 语句块后面的代码。

以下任何一个关系运算符都可以用来形成条件:

== 等于

!= 不等于

大于

< 小于

= 大于或等于

<= 小于或等于

下面是一个例子:

int x = 5;
if(x < 35) {
   System.out.println("Good");
}

if ... else语句

一个 if 语句后面可以跟 else 语句,当 if 语句的布尔表达式值为 false 时,else 语句块会被执行。

if…else 的用法如下:

if(布尔表达式){
   //如果布尔表达式的值为true
}else{
   //如果布尔表达式的值为false
}

下面是一个例子:

int age = 28;

if (age < 18) {
   System.out.println("Too Young");
} else { 
   System.out.println("Welcome!");
}
//输出 "Welcome"

当 age 等于28时,if 语句中的条件值为 false,并执行 else 语句。

嵌套 if 语句

嵌套 if 语句

你可以在另一个 if 或者 else 语句中使用一个 if-else 语句。

下面是一个例子:

int age = 28;
if(age > 0) {
   if(age > 18) {
      System.out.println("Welcome!");
   } else {
      System.out.println("Too Young");
   }
} else {
   System.out.println("Error");
}
//输出 "Welcome!"

提示:你可以按需嵌套更多的 if-else 语句。


else if 语句

else if 语句

if 语句后面可以跟 elseif…else 语句,这种语句可以检测到多种可能的情况。

语法格式如下:

if(布尔表达式 1){
   //如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
   //如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
   //如果布尔表达式 3的值为true执行代码
}else {
   //如果以上布尔表达式都不为true执行代码
}

下面是一个例子:

int x = 30;

if(x == 10) {
   System.out.println("x的值为10");
} else if(x == 20) {
   System.out.println("x的值为20");
} else if(x == 30) {
   System.out.println("x的值为30");
} else {
   System.out.println("这是else语句");
}
//输出 "x的值为30"

使用 if,else if,else 语句的时候,需要注意下面几点:
*if 语句至多有 1 个 else 语句,else 语句在所有的 else if 语句之后。
*if 语句可以有若干个 else if 语句,它们必须在 else 语句之前。
*一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。


逻辑语句

逻辑运算符

逻辑运算符用于组合多个条件。

假设你想要让你的程序输出 “Good!” ,只有当变量 a 大于10并且变量 b 大于20时。

一种方法是使用嵌套的 if 语句:

if (a > 10) {
   if (b > 20) {
      System.out.println("Good!");
   }
}

但是,使用逻辑与运算符(&&)是一个更好的方法:

if (a > 10 && b > 20) {
   System.out.println("Good!");
}

提示:逻辑与运算符,当且仅当两个操作数都为true,条件才成立。


逻辑或、逻辑非操作符

逻辑或运算符( || ) 检查是否有任何一个条件为真。

如果任何两个操作数任何一个为真,条件为真。

下面是一个例子:

int a = 15;
int b = 30;

if (a > 10 || b > 50) {
   System.out.println("Good!");
}
//输出 "Good!"

上面的代码将输出 “Good!”。

逻辑非运算符( ! ) 用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false

下面是一个例子:

int score = 85;
if(!(score > 60)) {
   System.out.println("Good luck!");
} else {
   System.out.println("Very good!");
}
//输出 "Very good!"

!(score > 60) 表示为 “score不大于60时”。

switch 语句

switch 语句

switch 语句判断一个变量一系列值中某个值是否相等,每个称为一个分支
switch 语法格式如下:

switch(expression){
    case value1 :
       //语句
       break; //可选
    case value2 :
       //语句
       break; //可选
    //你可以有任意数量的case语句
    default : //可选
       //语句
}

switch 语句有如下规则:

*当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。
*当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。
*case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。

下面是一个例子:

int num = 3;

switch(num) {
  case 1:
    System.out.println("数量为1");
    break;
  case 2:
    System.out.println("数量为2");
    break;
  case 3:
    System.out.println("数量为3");
    break;
}
// 输出 "数量为3"

提示:switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值冒号


default 语句

switch 语句可以包含一个 default 分支,该分支必须是 switch 语句的最后一个分支。

下面是一个例子:

int num = 3;

switch(num) {
  case 4:
    System.out.println("数量为4");
    break;
  case 5:
    System.out.println("数量为5");
    break;
  default:
    System.out.println("未知数量");
}
// 输出 "未知数量"

default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。

while 循环

while 循环

循环语句允许重复执行一个语句或一组语句。

while是最基本的循环,它的结构为:

while( 布尔表达式 ) {
  //循环内容
}

只要布尔表达式为 true,循环体会一直执行下去。

下面是一个例子:

int x = 5;

while(x < 10) {
   System.out.println(x);
   x++;
}
/* 
输出 
  5
  6
  7
  8
  9
*/

while 循环检查 x < 10的条件。如果它的值为 true,它将执行其正文中的语句。然后再次检查声明并重复。

while 循环

当检测布尔表达式为 false 时,将跳过循环体,并执行 while 循环后的第一条语句。

下面是一个例子:

int x = 5;

while( x < 10 )
{
  System.out.println(x);
  x++;
}
System.out.println("Loop ended");

/*
输出
 5
 6
 7
 8
 9
 Loop ended
*/

for 循环

for 循环

Java 提供了另一种语句是 for 循环,使一些循环结构变得更加简单。

for 循环执行的次数是在执行前就确定的。语法格式如下:

for(初始化; 布尔表达式; 更新) {
    //代码语句
}

关于 for 循环有以下几点说明:
*最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
*然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
*执行一次循环后,更新循环控制变量。
*再次检测布尔表达式。循环执行上面的过程。

下面是一个例子,输出数字1到3。

for(int x=1; x<=3; x++) {
  System.out.println(x);
}

/* 输出
1
2
3
*/

提示:注意语法中初始化和条件之后,使用的是分号( ; )。


for 循环

for 循环中可以有任何类型的布尔表达式和任何类型的增量语句。

下面的例子中,输出0到6之间的偶数值:

for(int x=0; x<=6; x=x+2) {
  System.out.println(x);
}
/* 输出
0
2
4
6
*/

image
image

do while 循环

循环控制语句

break 和 continue 语句改变了循环的执行流程。

break 语句终止循环并将执行转移到循环后面的语句。

下面是一个例子:

int x = 1;

while(x > 0) {
 System.out.println(x);
  if(x == 5) {
    break;
  }
  x++;
}

/* 输出
 1
 2
 3
 4
 5
*/

continue 语句会导致循环跳过其正文的其余部分,然后在重复之前立即重新检测其条件。也就是说,它使循环跳转到下一次迭代。

下面是一个例子:

for(int x=5; x<=20; x=x+5) {
  if(x == 15) {
    continue;
  }
  System.out.println(x);
}
/* 输出
  5
  10
  20
*/

如你所见,上面的代码按照 continue 语句的指令跳过了15的值。

数组

数组

数组是用来存储固定大小的同类型元素。
当你需要存储数值列表(如数字)时,可以将它们存储在数组中,而不是为每个数字声明单独的变量。

要声明一个数组,你需要用方括号定义元素的类型。

下面是一个例子,声明一个整数数组:

int[] arr;

上面的例子中,数组的名字是arr。它将包含的元素的类型是int。

Java 语言使用 new 操作符来创建数组,例如:

int[] arr= new int[10];

上面的例子中,声明了一个由10个整数组成的数组。

在一个数组中,这些元素是有序的,并且每个元素都有一个特定的和固定的位置,这个位置被称为索引。

要引用数组中的元素,请在一对方括号内键入数组名称,后跟索引位置。

下面是一个例子:

arr[2] = 20;

提示:数组的元素是通过索引访问的,数组索引从0开始,而不是1。所以,数组int[10]的最大索引是9。


初始化数组

Java 初始化数组是非常便捷的。

如果已经知道插入到数组中的值,则可以使用数组字面值。

数组字面值允许我们声明我们需要的元素个数并指定数据类型。

下面是一个初始化数组的例子,将值放在逗号分隔的列表中,并用花括号括起来。

String[] myList = {"a","b","c","d","e"};
System.out.println(myList[3]);

// 输出 "d"

上面的例子中,自动初始化一个包含5个元素的数组,并存储提供的值。


提示:声明数组变量时,将 [] 操作符放在数组名后面(如String myList[];),效果是相同的,但首选的方法是将 [] 操作符放在数组的数据类型之后(如String[] myList;)。


处理数组

数组长度

在 Java 中,你可以通过 length 属性来计算一个数组的长度,也就是所存储的元素的数量。

下面是一个例子:

int[] myArray = new int[10];
System.out.println(myArray.length);

// 输出 10

处理数组

现在我们知道如何设置和获取数组元素,我们可以使用循环来计算数组中所有元素的总和。

for 循环是使用数组时最常用的循环,因为我们可以使用数组的长度来确定运行循环的次数。

下面是一个例子:

int[] myArray = {2, 9, 7, 8};
int sum=0;
for(int i=0; i<myArray.length; i++) {
   sum += myArray[i];
}
System.out.println(sum);

// 输出 26

在上面的例子中,我们声明了一个变量sum来存储结果并赋值为0。

然后,我们用一个for循环遍历数组,并将每个元素的值添加到变量中。


提示:for循环的条件是 i<myArray.length,因为最后一个元素的索引是 myArray.length-1。


增强型for循环

增强型for循环

增强型for循环(或者称为foreach循环)用于遍历数组中的元素。

它能在不使用下标的情况下遍历数组。

下面是一个例子:

int[] intArray= {3, 5, 7, 9};

for (int a: intArray) {
   System.out.println(a); 
}

/* 输出
3
5
7
9
*/

增强型for循环声明了一个与被访问数组元素兼容的变量。该变量将在for块中可用,其值将与当前数组元素相同。

因此,在循环的每次迭代中,变量 a 将等于数组中的对应元素。


提示:记住语法中的变量后面使用的是冒号( : )。


多维数组

多维数组

多维数组可以看成是数组的数组,二维数组是最基本的多维数组。

要创建多维数组,请将每个数组放在其自己的一组方括号内。

下面是一个二维数组的例子:

int[][] num = {{1,2,3},{4,5,6}}; 

在上面的例子中,声明了一个有两个数组作为其元素的数组。

要访问二维数组中的元素,需要提供两个索引,一个用于数组,另一个用于该数组中的元素。

下面是一个例子,用于访问第二个num数组中的第一个元素。

int x = num[1][0];
System.out.println(x);

// 输出 4

提示:数组的两个索引称为行索引和列索引。


多维数组

在 Java 中,你可以使用同一对方括号来获取并设置多维数组的元素。

下面是一个例子:

int[][] myArray = {{1, 2, 3}, {4}, {5, 6, 7}};
myArray[0][1] = 30;
int x = myArray[1][0]; 

// 输出 4

上面的二维数组包含三个数组。第一个数组有三个元素,第二个数组有一个元素,第三个数组有三个元素。


提示:

在 Java 中,你可以设置多维数组,可以在数组中无限嵌套数组。但是,这将极为不好维护。

请记住,所有数组成员类型必须是相同的。


面向对象编程

面向对象

Java 使用面向对象编程(Object-Oriented Programming,OOP),这是一种编程风格,它旨在使思考编程更接近思考现实世界。

java 中的对象

在面向对象中,每个对象都是一个独立的单位,就像现实世界中的对象一样。

看看周围真实的世界,会发现身边有很多对象,车,猫,人等等。所有这些对象都有自己的状态和行为。

拿一只猫来举例,它的状态有:猫名、猫龄、颜色,行为有:睡觉、吃食和发出声音。

对比现实对象和软件对象,它们之间十分相似。

软件对象也有状态和行为。软件对象的状态就是属性,行为通过方法体现。

在软件开发中,方法操作对象内部状态的改变,对象的相互调用也是通过方法来完成。

Java 中的类

一个类描述对象将是什么,但是与对象本身是分开的。

换句话说,类可以描述为对象的模板,描述或定义。

您可以使用相同的类作为创建多个对象的模板。第一步是定义类,然后成为对象创建的模板。

每个类都有一个名称,每个类都用于定义属性和行为。

下面通过一个简单的类来理解Java中类的定义:

public class Cat{
  String name;
  int age;
  String color;
  void sleeping(){
  }

  void eating(){
  }

  void barking(){
  }
}

方法

方法

在 Java 中,方法定义行为。一个方法是一个组合在一起执行操作的语句的集合。System.out.println() 是一个方法的例子。

您可以定义自己的方法来执行所需的任务。

下面是一个例子:

class MyJavaClass {

  static void sayHello() {
    System.out.println("Hello Edong!");
  }

  public static void main(String[] args) {
    sayHello();
  }
}
// 输出 "Hello Edong!"

在上面的例子中,声明了一个名为 “sayHello” 的方法,它会输出一行文本,然后在 main 方法中调用。


提示:若要调用一个方法,请输入其名称,然后在名称后面加上一组圆括号。


方法调用

在 Java 中,您可以根据需要多次调用方法。

当一个方法运行时,代码会跳转到方法定义的位置,执行它内部的代码,然后返回到下一行。

下面是一个例子:

class MyJavaClass {
  
  static void sayHello() {
    System.out.println("Hello Edong!");
  }

  public static void main(String[] args) {
    sayHello();
    sayHello();
    sayHello();
  }
}

// Hello Edong!
// Hello Edong!
// Hello Edong!

方法参数

您也可以创建一个方法,在调用它时将一些数据称为参数。在方法的括号内写入参数。

例如,我们可以修改我们的 sayHello() 方法来获取并输出一个字符串参数。

class MyJavaClass {
  static void sayHello(String name) {
    System.out.println("Hello " + name);
  }
  public static void main(String[] args) {
    sayHello("Loen");
    sayHello("Shuter");
  }
}

// Hello Loen
// Hello Shuter

上面的方法将一个名为 name 的字符串作为参数,用在方法的主体中。

然后,在调用方法时,我们将参数的值传递给括号。


提示:在 Java 中,方法可以采用多个以逗号分隔的参数。


方法返回类型

返回类型

返回关键字可用于方法返回值。

例如,我们可以定义一个名为sum的方法,返回两个参数的总和。

static int sum(int val1, int val2) {
   return val1 + val2;
}

在方法定义中,我们在定义方法名称之前定义了返回类型。对于sum方法,它是int类型,因为它采用int类型的两个参数,并返回它们的总和,这也是一个int类型。

提示: 关于static关键字的知识,我们将在后面的小节中去了解学习。

现在,我们可以使用我们main的方法。

class MyJavaClass {

  static int sum(int val1, int val2) {
    return val1 + val2;
  }

  public static void main(String[] args) {
    int x = sum(3, 6);
    System.out.println(x);
  }
}

// 输出 "9"

当该方法返回一个值时,我们可以将其赋值给一个变量。


提示:

如果不需要从方法中返回任何值,请使用关键字void。

注意main方法定义中的void关键字,这意味着main不返回任何内容。


返回类型

通过前面小节的学习介绍,我们可以更好地理解程序是如何工作的:

// 返回一个int值 6
static int returnSix() {
  return 6;
}

// 输出传入的参数
static void sayHelloTo(String name) {
  System.out.println("Hello " + name);
}

// 打印 "Hello Lu!"
static void sayHello() {
  System.out.println("Hello Lu!");
}

在了解方法返回类型和参数的知识之后,我们再来看看main方法的定义。

 public static void main(String[] args)

这个定义表明main方法以一个字符串数组作为参数,并且不返回任何值。

返回类型

让我们创建一个方法,它采用int类型的两个参数,并返回这两个参数的最大值,然后在main中调用它:

public static void main(String[] args) {
  int result = max(5, 35);
  System.out.println(result); // 35
}

static int max(int x, int y) {
  if(x > y) {
    return x;
  }
  else {
    return y;
  }
}

创建类和对象

创建类

为了创建自己的自定义对象,你必须先创建相应的类。

你可以使用Eclipse开发工具,通过右键点击src目录,并选择 New(新建)-> Class(类)。

给你的类提供一个名称,然后点击 “Finish(完成)” 将新类添加到项目中。结果如下图所示:
image

如你所见,Eclipse已经为这个类添加了初始代码。

现在,让我们在新类中创建一个简单的方法。

Animal.java 文件代码:

public class Animal {
  void barking() {
    System.out.println("Meow-Meow");
  }
}

在上面的代码中,我们在Animal类中声明了一个barking()方法。


提示:为了使用类和它的方法,我们需要声明这个类的一个对象。


创建对象

对象是根据类创建的。在Java中,使用关键字new来创建一个新的对象。

下面是一个创建对象的例子:

class Animal {
  public static void main(String[] args) {
    Animal cat = new Animal();
    cat.barking();
  }
}
// 输出 "Meow-Meow"

在上面的例子中,cat 是 Animal 的对象。因此,我们可以使用对象的名称和点来调用它的barking()方法。


提示:点符号用于访问对象的属性和方法。


image

类属性

定义属性

一个类有属性和方法。属性基本上是一个类中的变量。

让我们创建一个名为 Dog 的类,它具有相应的属性和方法。

public class Dog {
  String name;
  int age;
  String color;

  void barking() {
    System.out.println("Woof-Woof");
  }  
}

在上面的例子中,name,age,和color是Dog类的属性,而barking()是唯一的方法。


提示:你可以根据需要定义多个属性和方法。


创建对象

接下来,我们可以创建Dog类的多个对象,并使用点符号来访问它们的属性和方法。

下面是一个例子:

class Dog {
  public static void main(String[] args) {
    Dog d1 = new Dog();
    Dog d2 = new Dog();
    d1.color = "white";
    d2.barking();
  }
}

image

访问修饰符

访问修饰符

现在,让我们来了解main方法前面的 public 关键字。

public static void main(String[] args)
public 是一个访问修饰符,它被用来设置访问级别。在 Java 中,可以使用访问修饰符来保护对类、变量、方法的访问。

Java 支持 4 种不同的访问权限。

default (即缺省,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类内可见。使用对象:变量、方法。
public: 对所有类可见。使用对象:类、接口、变量、方法
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。
下面是一个例子:

public class Dog {
  private String name;
  private int age;
  private String color;

  public void barking() {
    System.out.println("Woof-Woof");
  }
}

注意: private 和 protected 修饰符不能修饰类(外部类)。


getter 和 setter方法

getter和setter方法

声明为私有访问类型的变量只能通过类中公共的getter/setter方法被外部类访问。

getter和setter方法主要用来隐藏类的实现细节和保护类的数据。

对于每个变量,get方法返回其值,而set方法设置该值。

getter方法以get开头,setter方法以set开始,后面都跟着变量名,变量名的第一个字母大写。

下面是一个例子:

public class Dog {
  private String color;

  // getter
  public String getColor() {
    return color;
  }

 // setter
  public void setColor(String c) {
    this.color = c;
  }
}

getter方法返回属性的值。setter方法接受一个参数并将其赋值给属性。


提示:关键字this用于引用当前对象。也就是说,this.color是当前对象的颜色属性。


image

getter和setter方法

一旦我们的getter和setter被定义了,我们可以在我们的main中使用它。

下面是一个例子:

public static void main(String[] args) {
  Dog d1 = new Dog();
  d1.setColor("White");
  System.out.println(d1.getColor());
}

//输出 "White"

getter和setter允许我们控制这些值。例如,您可以在实际设置该值之前在设置器中验证给定的值。


提示:getter和setter是封装的基本构建块,你将在后面的章节中去了解学习。


构造函数

构造函数

构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值。

可以使用构造函数为对象属性提供初始值。

构造函数名称必须与其类名相同。
构造函数不能有明确的返回类型。
下面是一个构造函数的例子:

public class Dog {
  private String color;
  Dog() {
     color = "White";
  }
}

Dog()方法是我们类的构造函数,所以无论何时创建该类的对象,color属性都将设置为“White”。

构造函数也可以带参数来初始化属性。

例如:

public class Dog {
  private String color;
  Dog(String c) {
    color = c;
  }
}

image

使用构造函数

new对象时,就调用与之对应的构造函数。

下面是一个例子:

public class MyJavaClass {
  public static void main(String[] args) {
    Dog d = new Dog("Yellow");
  }
}

这将调用构造函数,将设置color属性为“Yellow”。

注:一般函数不能调用构造函数,只有构造函数才能调用构造函数。

构造函数

一个类可以有多个构造函数,它们具有不同数量的参数。

构造函数中的setter方法可以用来设置属性值。

下面是一个例子:

public class Dog {
  private String color;

  Dog() {
    this.setColor("White");
  }
  Dog(String c) {
    this.setColor(c);
  }

  // setter
  public void setColor(String c) {
    this.color = c;
  }
}

上面的类有两个构造函数,一个没有任何参数,将color属性设置为默认值“White”,另一个构造函数接受一个参数并将其赋值给属性。

现在,我们可以使用构造函数来创建我们的类的对象。

//颜色将是"White"
Dog d1 = new Dog();

//颜色将是"Yellow"
Dog d2 = new Dog("Yellow"); 

提示:Java 会自动提供一个默认的构造函数,所以所有的类都有一个构造函数,无论是否有特殊的定义。


image

值和引用类型

值类型

基本类型 包括 byte,short,int,long,float,double,boolean和char。

Java方法参数传递的到底是值还是引用?

基本类型传的是变量的值。
image

所以,当你将它们传递给一个方法时,你基本上是对变量的值进行操作,而不是对变量本身进行操作。

最常见的说法是基本类型传的是值,对象传的引用。

下面是一个例子:

public class MyJavaClass {
  public static void main(String[] args) {
    int x = 10;
    addTo(x); // 这时候等价于 addTo(10)
    System.out.println(x);       
  }
  static void addTo(int num) {
    num = num + 1;
  }
}
// 输出 "10"

在上面的例子中,方法取其参数的值,这就是为什么原始变量x不受影响,10仍然是x的值。

值类型易错题image

引用类型

引用类型传递的是对象地址值,而非对象或副本。
image

当你使用构造函数创建对象时,你将创建一个引用变量。

例如,我们要定义一个Student类:

public class MyJavaClass {
  public static void main(String[] args) {
    Student j;
    j = new Student("Jing"); /*student是一个类,
               		     j是student的一个对象,
   			     new创建了这个实例j,为其分配变量,
    			     又可以写成Student j = new Student("Jing");
			     */
    j.setAge(18);
    addTo(j);
    System.out.println(j.getAge());
  }
  static void addTo(Student s) {
    s.setAge(s.getAge() + 1);
  }
}
//输出 "19"

addTo方法Student类的对象作为参数,并增加其属性。

由于 j 是引用类型,因此addTo方法影响Student类的对象本身,并且可以更改其属性的实际值


提示:数组和字符串也是引用类型。


引用类型易错题

image

Math 类

Math 类

JDK定义了许多有用的类,其中一个是Math类,它为数学运算提供了预定义的方法。

你不需要创建Math类的对象来使用它。要访问它,只需输入Math. 和相应的方法。

Math.abs() 返回参数的绝对值。参数可以是 int, float, long, double, short, byte类型。

int a = Math.abs(5);  // 5
int b = Math.abs(-10); // 10

Math.ceil() 将一个数进行上舍入,返回值大于或等于给定的参数。

double c = Math.ceil(6.231);  // 7.0

Math.floor() 将对一个数进行下舍入,返回给定参数最大的整数,该整数小于或等给定的参数。

double f = Math.floor(6.231);  // 6.0

Math.max() 用于返回两个参数中的最大值。

int m = Math.max(5,10);  // 10

相反,Math.min() 用于返回两个参数中的最小值。

int m = Math.min(5,10);  // 5

Math.pow() 用于返回第一个参数的第二个参数次方。值以double形式返回。

double p = Math.pow(2,3); // 8.0

提示:Math 类还提供了其他一些方法,例如:sqrt(),sin(),cos() 方法等等。


Math类题目

image

static 修饰符

静态变量

当你声明一个变量或方法为静态时,它属于这个类,而不是一个特定的实例。

不管你创建了该类的多个对象,或者如果你不创建任何对象, 有且只有一个静态成员的实例存在。

该静态成员将被所有对象共享。

static 关键字用来声明独立于对象的静态变量。

下面是一个例子:

public class Counter {
  public static int numCount = 0;
  Counter() {
    numCount++;
  }
}

numCount 变量将被该类的所有对象共享。

现在,我们可以在main中创建Counter类的对象,并访问静态变量。

public class MyJavaClass {
  public static void main(String[] args) {
    Counter c1 = new Counter();
    Counter c2 = new Counter();
    System.out.println(Counter.numCount);
  }
}
//输出 "2"

上面代码的输出结果是2,因为numCount变量是静态的,每次创建一个Counter类的新对象时都会增加1,而在代码中,我们创建了2个对象。

你也可以使用该类的任何对象(如c1.numCount)来访问静态变量。

静态方法

相同的概念也适用于静态方法。static 关键字用来声明独立于对象的静态方法。

下面是一个例子:

public class Dog {
  public static void barking() {
    System.out.println("Woof-Woof");
  }
}

现在,可以在不创建对象的情况下调用barking方法:

public class MyJavaClass {
  public static void main(String[] args) {
    Dog.barking();
  }
}

静态方法的另一个例子是Math类,这就是为什么你可以在不创建Math对象的情况下调用它们的原因。


提示:main方法必须始终是静态的。


final 修饰符

final

使用 final 关键字标记一个常量,常量只能被赋值一次。

final 修饰符通常和 static 修饰符一起使用来创建类常量。

下面是一个例子:

class MyJavaClass {
  public static final double PI = 3.14; 
  public static void main(String[] args) {
    System.out.println(PI);
  }
}

PI 现在是一个常量。任何为其赋值的尝试都会输出错误。


提示: 方法和类也可以标记为 final,这样做可以限制方法,使其不能被重写,并且不能使其成为子类。在后面的章节中,我们将进一步的介绍有关知识。


包(package)

包(package)

Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类、接口、枚举和注释等。

一个包(package)可以定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。

用Java创建一个包是非常简单的。使用Eclipse开发工具,通过右键点击项目中的src目录,并选择 New(新建)-> Package(包)。为这个包取一个合适的名字(例如:w3cschool),然后点击 “Finish(完成)” 。

你会注意到新的包出现在项目目录中。现在你可以在这个包里面创建和移动类。结果如下图所示:
image

在包中创建/移动类时,以下代码将出现在文件列表的顶部。

package w3cschool;

这表示这个类所属的包。

现在,我们需要导入包中的类,以便能够使用它们。

下面是一个例子,显示如何使用w3cschool包的Cat类。

import w3cschool.Cat;

class MyJavaClass {
  public static void main(String[] args) {
    Cat c1 = new Cat();
    c1.barking();
  }
}

当一个类被放入一个包中时会发生两个主要的结果。首先,包的名称成为该类名称的一部分。其次,包的名称必须与相应的类文件所在的目录结构相匹配。


提示:使用通配符 "*" 导入包中的所有类。例如,import w3cschool.* 将导入w3cschool包中的所有类。


封装

封装

面向对象编程(OOP)的主要特征是:封装,继承,多态。

封装背后的想法是确保实现细节对用户不可见。

一个类的变量将被其他类隐藏,只能通过当前类的方法访问。这被称为数据隐藏。

为了在Java中实现封装,将类的变量声明为private,并提供public getter和setter方法来修改和查看变量的值。

下面是一个例子:

class BankAccount {
  private double balance = 0;
  public void deposit(double x) {
    if(x > 0) {
      balance += x;
    }
  }
}

这段代码中,实现隐藏了balance变量,只能通过deposit方法来访问它,在修改变量之前验证了要存入的金额。

总之,封装提供了以下优点:

*良好的封装能够减少耦合。
*类内部的结构可以自由修改。
*可以对成员变量进行更精确的控制。
*隐藏信息,实现细节。

封装题目

image

继承

继承

继承是使一个类获得另一个类的属性(方法和变量)的过程。通过继承,信息被放置在更易于管理的层次上。

继承另一个属性的类称为子类(也称为派生类)。其属性被继承的类称为父类(基类或超类)。

在 Java 中,通过extends 关键字可以申明一个类是从另外一个类继承而来的。

下面是一个例子,展示了如何让类 Cat 继承 Animal 类

class Cat extends Animal {
 // 其余代码
}

在这里,Cat 是子类,Animal 是父类。

继承

当一个类从另一个类继承时,它继承了所有父类的非私有变量和方法。

下面是一个例子:

class Animal {
  protected int legs;
  public void eat() {
    System.out.println("Animal eats");
  }
}

class Cat extends Animal {
  Cat() {
    legs = 4;
  }
}

如你所见,Cat 类继承了 Animal 类中的 legs 变量。

现在,我们可以声明一个 Cat 对象,并调用它的父类的 eat 方法:

class MyJavaClass {
  public static void main(String[] args) {
    Cat c = new Cat();
    c.eat();
  }
}

提示:protected 访问修饰符,protected 使成员只对子类可见。


继承题目

image

继承

构造函数不是成员方法,所以不会被子类继承。

然而,父类的构造函数在子类被实例化时会被调用。

下面是一个例子:

class A {
  public A() {
    System.out.println("New A");
  }
}
class B extends A {
  public B() {
    System.out.println("New B");
  }
}

class Test {
  public static void main(String[] args) {
      B obj = new B();
  }
}

/*输出
"New A"
"New B"
*/

提示:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。例如,super.var 将访问父类的var成员。


继承题目

image
构造函数不是成员方法,所以不会被子类继承。

多态

多态

多态是同一个行为具有多个不同表现形式或形态的能力。多态性是对象多种表现形式的体现。

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

多态的优点

  1. 消除类型之间的耦合关系
  2. 可替换性
  3. 可扩充性
  4. 接口性
  5. 灵活性
  6. 简化性

多态存在的三个必要条件

*继承
*重写
*父类引用指向子类对象
下面是一个例子,Cat 和 Dog 是继承 Animal 类的类。每个类都有自己的 barking() 方法的实现。

class Animal {
  public void barking() {
    System.out.println("Hi");
  }
}
class Cat extends Animal {
  public void barking() {
    System.out.println("Meow-Meow");
  }
}
class Dog extends Animal {
  public void barking() {
    System.out.println("Woof-Woof");
  }
}

由于所有 Cat 和 Dog 对象都是 Animal 对象,我们可以主要执行以下操作:

public static void main(String[] args) {
  Animal a = new Dog();
  Animal b = new Cat();
}

我们创建了两个类型为 Animal 的引用变量,并将它们指向 Cat 和 Dog 对象。

现在,我们可以调用 barking() 方法。

a.barking();
//输出 "Woof-Woof"

b.barking();
//输出 "Meow-Meow"

由于引用变量 a 指向 Dog 对象,Dog 类的 barking() 方法将被调用。这同样适用于 b 变量。


提示:这表明,你可以使用Animal变量而不需要知道它包含了子类的一个对象。当你有父类的多个子类时,这是非常有用的。


重写和重载

方法重写

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写。

重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。

下面是一个例子:

class Animal {
   public void barking() {
      System.out.println("Hi");
   }
}
class Dog extends Animal {
   public void barking() {
      System.out.println("Woof-Woof");
   }
}

在上面的代码中,Dog 类重写了其父类 Animal 的 barking() 方法。

方法的主要重写规则:

*必须有相同的参数列表和返回类型。
*访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
*声明为final或static的方法不能被重写。
*构造方法不能被重写。
*如果不能继承一个方法,则不能重写这个方法。

方法重载

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

最常用的地方就是构造器的重载。

重载规则:

*被重载的方法必须改变参数列表(参数个数或类型不一样);
*被重载的方法可以改变返回类型;
*被重载的方法可以改变访问修饰符;
*被重载的方法可以声明新的或更广的检查异常;
*方法能够在同一个类中或者在一个子类中被重载。
*无法以返回值类型作为重载函数的区分标准。
例子:

public class Overloading {
    public int test(){
        System.out.println("test1");
        return 1;
    }
 
    public void test(int a){
        System.out.println("test2");
    }   
 
    //以下两个参数类型顺序不同
    public String test(int a,String s){
        System.out.println("test3");
        return "returntest3";
    }   
 
    public String test(String s,int a){
        System.out.println("test4");
        return "returntest4";
    }   
 
    public static void main(String[] args){
        Overloading o = new Overloading();
        System.out.println(o.test());
        o.test(1);
        System.out.println(o.test(1,"test3"));
        System.out.println(o.test("test4",1));
    }
}

提示:被重载的方法必须改变参数列表(参数个数或类型或顺序不一样)。


重写和重载题目

image

与重载之间的区别

image

总结

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

(1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。

(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。

(3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
image
image

抽象

抽象概念

数据抽象为外界提供了仅有的基本信息,在表示基本特征的过程中不包括实现细节。

举个真实世界的例子,比如一本书。当你听到是书时,你不知道具体的细节,如页数,颜色或大小,但你明白书的概念、大概模样。这就是对书的抽象。

抽象的概念是我们关注基本特征,而不是一个特定例子的具体特征。

在 Java 中,抽象是使用抽象类和接口实现的。

抽象类是使用 abstract 关键字定义的。

*如果一个类声明为抽象类,则不能被实例化(不能创建该类型的对象)。
*要使用抽象类,必须从另一个类继承它。
*抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类


提示:抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。如:abstract void run();


抽象类

例如,我们可以将 Animal 类定义为抽象类:

abstract class Animal {
  int legs = 0;
  abstract void barking();
}

barking 方法也是抽象的,因为它在父类中没有实现。

我们可以继承 Animal 类并为子类定义 barking() 方法:

class Dog extends Animal {
  public void barking() {
    System.out.println("Woof-Woof");
  }
}

每种动物都会发出声音,但每种动物都有不同的叫声。这就是我们为什么要定义一个抽象类 Animal 的原因,并且把它们如何发出声音的实现留给子类。

image

接口

接口

一个接口是一个完全抽象的类,只包含抽象方法。接口通常以interface来声明。

接口的一些规则:

*类里面可以声明 public static final 修饰的变量。
*接口不能被实例化,但是可以被实现类创建。
*一个类可以实现多个接口。
*一个接口能继承另一个接口,这和类之间的继承比较相似。

下面是一个简单的接口例子:

interface Animal {
  public void eating();
  public void barking();
}

接口有以下特性:
接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
接口中的方法都是公有的。


提示:一个类只能继承一个类,但是能实现多个接口。


接口的实现

当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

类使用 implements 关键字实现接口。在类声明中,Implements 关键字放在 class 声明后面。

下面是一个例子:

interface Animal {
  public void eating();
  public void barking();
}

class Dog implements Animal {
  
  public void eating() {
    System.out.println("crunch-crunch");
  }
  public void barking() {
    System.out.println("Woof-Woof");
  }
}

提示:当你实现一个接口时,你需要重写所有的方法。


接口题目

image

类型转换

类型转换

将一个类型的值赋给另一个类型的变量称为类型转换。

要将值转换为特定类型,请将该类型放在括号中,并将其放在值的前面。

下面是一个例子:

int x = (int)5.25;
System.out.println(x);

//输出 5

上面的代码中,将值5.25转换为一个整数,输出5为结果值。

再来看另外一个例子:

double x = 27.582;
int y = (int)x;
System.out.println(y);

//输出 27

提示:Java 支持将整数自动类型转换为浮点,因为没有精度损失。另外,在将浮点值赋值给整型变量时,强制类型转换是强制性的, 可能会有进度损失。


类型转换题目

image

向上转型和向下转型

向上转型和向下转型

对于类,有两种类型的转换。

向上转型(Upcasting)

您可以将一个子类的实例转换为其父类。这是向上转换。

下面是一个例子,比如 Dog 是 Animal 的一个子类。

Animal a = new Dog();

Java 自动将 Dog 类型的变量上传到 Animal 类型。

向下转型(Downcasting)

将父类的对象转换为其子类称为向下转换。

下面是一个例子:

Animal a = new Animal();
((Dog)a).barking();

上面的代码中,尝试将变量 a 转换为 Dog 类型并调用其 barking() 方法。

向上转型和向下转型题目

image

匿名类

匿名类

匿名类是一种即时继承现有类的方法。

例如,下面有一个类 Computer:

class Computer {
  public void start() {
    System.out.println("Starting");
  }
}

创建 Computer 对象时,我们可以即时更改 start 方法。

public static void main(String[] args) {
  Computer c = new Computer() {
    @Override public void start() {
      System.out.println("Wooooo");
    }
  };
  c.start();
}
// 输出 "Wooooo";

在构造函数调用之后,我们使用花括号,并且重写了 start 方法的实现。


提示:@Override注解用于使代码更容易理解,因为当方法被重写时,它更加明显。


匿名类题目

image

匿名类

修改只适用于当前对象,而不适用于类本身。所以,如果我们创建这个类的另一个对象,那么 start 方法的实现就是在类中定义的那个。

class Computer {
  public void start() {
    System.out.println("Starting");
  }
}  
public static void main(String[] args) {
  Computer c1 = new Computer() {
    @Override public void start() {
      System.out.println("Wooooo");
    }
  };
  Computer c2 = new Computer();
  c2.start();
  }

//输出 "Starting"

匿名类题目

image

内部类

内部类

Java 支持嵌套类,一个类可以是另一个类的成员。

创建一个内部类很简单,只要在类中编写一个类。

作用:

*实现了更好的封装,我们知道,普通类(非内部类)的访问修饰符不能为private或protected,而内部类可以。当我们将内部类声明为private时,只有外部类可以访问内部类,很好地隐藏了内部类。
*内部类可以继承(extends)或实现(implements)其他的类或接口,而不受外部类的影响。
*内部类可以直接访问外部类的字段和方法,即使是用private修饰的,相反的,外部类不能直接访问内部类的成员。
下面是一个例子:

class Robot {
  int id;
  Robot(int i) {
    id = i;
    Brain b = new Brain();
    b.think();
  }

  private class Brain {
    public void think() {
      System.out.println(id + " is thinking");
    }
  }
}

提示:类Robot有一个内部类Brain。内部类可以访问外部类的所有成员变量和方法,外部类不能直接访问内部类的成员。


内部类题目

image

equals() 方法

比较对象

请记住,当你创建对象时,变量存储的是对象的引用。

所以,当使用(==)比较对象时,它实际上比较的是引用而不是对象值。

下面是一个例子:

class Animal {
  String name;
  Animal(String n) {
    name = n;
  }
}

class MyJavaClass {
  public static void main(String[] args) {
    Animal a1 = new Animal("Kitty");
    Animal a2 = new Animal("Kitty");
    System.out.println(a1 == a2);
  }
}
//输出 false

提示:尽管有两个名称相同的对象,因为我们有两个不同的对象(两个不同的引用或内存位置),所以相等性测试返回 false。


比较对象题目

image

equals()

每个对象都有一个预定义的equals()方法,用于语义相等性测试。

但是,为了使它适用于我们的类,我们需要重写它,并检查我们需要的条件。

有一个简单而快速的方法来生成 equals() 方法,你不需要手动编写。

你只需右键单击你的类,选择 Source -> Generate hashCode() and equals()...来完成,如下图所示:
image

这将自动创建必要的方法。如下面例子所示:

class Animal {
  String name;
  Animal(String n) {
    name = n;
  }
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Animal other = (Animal) obj;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    return true;
  }
}

自动生成的hashCode()方法用于确定内部存储对象的位置。每当你实现equals时,你也必须实现hashCode。

我们可以使用equals方法再次运行测试:

public static void main(String[] args) {
  Animal a1 = new Animal("Kitty");
  Animal a2 = new Animal("Kitty");
  System.out.println(a1.equals(a2));
}

//输出 true

提示:你可以使用相同的操作来生成其他有用的方法,例如:类属性的getter和setter方法。


枚举

枚举

枚举是Java1.5引入的新特性,通过关键字 enum 来定义枚举类。

枚举类是一种特殊类,它和普通类一样可以使用构造器、定义成员变量和方法,也能实现一个或多个接口,但枚举类不能继承其他类.

枚举类型使用的最常用类型就是枚举常量。

下面是一个简单的枚举例子:

enum Rank {
  BRONZE,
  SILVER,
  GOLD
}

请注意,这些值是用逗号分隔的。

你可以使用点符号在上面的枚举中引用常量。

Rank a = Rank.BRONZE;

提示:枚举定义了代表固定集成员的变量。


枚举

声明一个枚举之后,我们可以检查相应的值,例如,一个switch语句。

Rank a = Rank.BRONZE;

switch(a) {
  case BRONZE:
    System.out.println("第三名!");
    break;
  case SILVER:
    System.out.println("第二名!");
  break;
  case GOLD:
    System.out.println("第一名!");
    break;
}

//输出 "第三名!"

枚举题目

image

枚举

当变量(特别是方法参数)只能从一小组可能的值中取出一个时,你应该总是使用枚举。


提示:枚举的使用示例,包括月份,星期几,颜色、学历、职业等。


枚举题目

image

使用Java API

Java API

Java API是为你编写的类和接口的集合。

包含所有可用API的Java API文档可以在Oracle网站上找到 (http://docs.oracle.com/javase/7/docs/api/)。

当找到想要使用的软件包,我们需要将其导入到代码中。使用import关键字导入。

下面是一个例子:

import java.awt.*;

awt 包中包含了用于创建用户界面和绘制图形图像的所有类。


提示:通配符(*)用于导入包中的所有类。


Java API题目

image

更多类小节训练

image

image
image
image

强制类型转换精度丢失
image
image

异常处理

异常

程序执行过程中出现异常。异常会导致程序异常终止。

异常处理是处理运行时错误以保持正常应用程序流的强大机制。

异常发生的原因有很多,通常包含以下几大类:

*用户输入了非法数据。
*要打开的文件不存在。
*网络通信时连接中断,或者JVM内存溢出。


提示:如你所见,这些异常有的是因为用户错误引起,有的是程序错误或物理错误引起的。但是,一个写得好的程序应该处理所有可能的异常情况。


异常处理

使用 try 和 catch 关键字可以捕获异常。

try/catch 代码块放在异常可能发生的地方。try/catch 代码块中的代码称为保护代码。

使用 try/catch 的语法如下:

try {
  //程序代码
} catch(Exception e) {
  //Catch 块
}

Catch 语句包含要捕获异常类型的声明。当 try 块中发生一个异常时,try 后面的 catch 块就会被检查。如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。

Exception 类型可以用来捕获所有可能的异常。

下面的例子中,说明了当尝试访问一个不存在的数组索引时的异常处理:

public class ExcepTest{
  public static void main(String[] args) {
    try {
      int a[] = new int[2];
      System.out.println(a[3]);
    } catch (Exception e) {
      System.out.println("An error occurred");
    }
  }
}

//输出 "An error occurred"

没有 try/catch 块,这段代码会导致程序崩溃,因为[3]不存在。


注意:catch 块中的(Exception e)语句,它用于捕获所有可能的异常。


异常处理

image

多重异常

throw

使用 throw 关键字可以手动生成方法中的异常。一些可用的异常类型包括 IndexOutOfBoundsException (非法索引访问数组时抛出的异常),IllegalArgumentException(非法参数异常),ArithmeticException(出现异常的运算条件时,抛出此异常) 等等。

例如,当参数为0时,我们可以在方法中抛出 ArithmeticException。

int div(int a, int b) throws ArithmeticException {
  if(b == 0) {
    throw new ArithmeticException("Division by Zero");
  } else {
    return a / b;
  }
}

方法定义中的throws语句定义了方法可以抛出的Exception的类型。

接下来,throw关键字会引发相应的异常,并附带自定义消息。

如果我们调用第二个参数等于0的div方法,它将抛出一个ArithmeticException,并带有“Zero by Division”消息。


提示:可以使用逗号分隔列表在 throws 语句中定义多个异常。


throw题目

image

异常处理

一个 try 代码块后面可以跟随多个 catch 代码块,这种情况就叫多重捕获,分别处理不同的异常。

多重捕获的语法如下所示:

try {
  // 程序代码
} catch (异常类型1 异常的变量名1) {
  // 程序代码
} catch (异常类型2 异常的变量名2) {
  // 程序代码
} catch (异常类型3 异常的变量名3) {
  // 程序代码
}

提示:所有 catch 块应该从最具体到最普遍的顺序排列。在特定的异常之后,您可以使用Exception类型来处理所有其他异常作为最后一个catch。


多线程编程

多线程编程

Java是一种多线程编程语言。我们的程序可以通过同时运行两个或多个组件来优化使用可用资源,每个组件处理不同的任务。

你可以将单个应用程序中的特定操作细分为全部并发运行的单个线程。

线程是一个动态执行的过程,它也有一个从出生到死亡的过程。下图显示了一个线程完整的生命周期。

image

Java 提供了两种创建线程的方法。

创建一个线程的第一种方法是创建一个新的类该类继承 Thread 类,然后创建一个该类的实例

继承类必须重写 run() 方法,该方法是新线程的入口点。它也必须调用start() 方法才能执行。

下面是一个例子:

class Loader extends Thread {
  public void run() {
    System.out.println("Hello Lu");
  }
}

class MyJavaClass {
  public static void main(String[] args) {
    Loader obj = new Loader();
    obj.start();
  }
}

如你所见,我们的Loader类继承了Thread类,并重写了它的run()方法。

当我们创建obj对象并调用它的start()方法时,run()方法语句在另一个线程上执行。


提示:每个Java线程都被赋予优先级,以帮助操作系统确定线程调度的顺序。优先级范围从1到10,每个线程默认优先级为5,你可以使用setPriority()方法设置线程优先级。


多线程编程题目

image

创建线程

创建一个线程的第二种方法实现Runnable接口。

实现run()方法。然后,创建一个新的Thread对象,将Runnable类传递给它的构造函数,并通过调用start()方法来启动Thread。

下面是一个例子:

class Loader implements Runnable {
  public void run() {
    System.out.println("Hello Lu");
  }
}

class MyJavaClass {
  public static void main(String[] args) {
    Thread t = new Thread(new Loader());
    t.start();
  }
}

Thread.sleep()方法将线程暂停指定的时间段。例如,调用Thread.sleep(1000);暂停一秒钟的线程。请记住,Thread.sleep()抛出一个InterruptedException,所以一定要用try/catch块来包围它。


提示:看起来,实现Runnable接口比从Thread类继承复杂一点。但是,实现Runnable接口是启动线程的首选方法,因为它使你可以从另一个类进行继承。

多线程编程题目

image


检查性和运行时异常

异常类型

在Java中,有两种异常类型,分别是检查性异常和运行时异常(又叫非检查异常)。

主要区别在于检查性异常在编译时被检查,而在运行时检查未经检查的异常。

检查异常是运行时异常以外的异常, 也是Exception及其子类, 这些异常从程序的角度来说是必须经过捕捉检查处理的, 否则不能通过编译. 如IOException、SQLException等

运行时异常都是RuntimeException类及其子类, 如 NullPointerException、IndexOutOfBoundsException等, 这些异常是不检查的异常, 是在程序运行的时候可能会发生的, 所以程序可以捕捉, 也可以不捕捉. 这些错误一般是由程序的逻辑错误引起的, 程序应该从逻辑角度去尽量避免.

正如在上一个小节中所提到的,Thread.sleep()抛出一个InterruptedException。这是一个检查性异常的例子。在处理异常之前,你的代码将不会编译。如下图所示:

代码如下:

public class MyJavaClass {
  public static void main(String[] args) {
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      // 其余代码
    }
  }
}

我们在之前的小节中,有遇到过运行时检查未经检查的异常例子。

下面是一个例子(尝试除以0):

public class MyJavaClass {
  public static void main(String[] args) {
    int value = 5;
    value = value / 0;
  }
}

/*
Exception in thread "main" java.lang.ArithmeticException: / by zero
  at MyJavaClass.main(MyJavaClass.java:4)
*/

题目

image

ArrayList

ArrayList

Java API 提供了特殊的类来存储和操作对象组。

有一个这样的类是ArrayList。标准Java数组的长度是固定的,它们在创建之后不能扩展或缩小。

另一方面,ArrayLists是使用初始大小创建的,但是当超过这个大小时,集合会自动增大。

当对象被删除时,ArrayList可能会缩小。请注意,ArrayList类在java.util包中,因此在使用它之前需要导入它。

像任何对象一样创建一个ArrayList。

import java.util.ArrayList;
//...
ArrayList colors = new ArrayList();

你可以选择指定ArrayList将保存的对象的容量和类型:

ArrayList<String> colors = new ArrayList<String>(5);

上面的代码定义了一个初始大小为5的String的ArrayList。

ArrryList题目

image

ArrayList

ArrayList类提供了许多有用的方法来处理它的对象。

add()方法将新对象添加到ArrayList。相反,remove()方法从ArrayList中移除对象。

下面是一个例子:

import java.util.ArrayList;

public class MyJavaClass {
  public static void main(String[] args) {
    ArrayList<String> colors = new ArrayList<String>();
    colors.add("Red");
    colors.add("Blue");
    colors.add("Green");
    colors.add("Orange");
    colors.remove("Blue");

    System.out.println(colors);
  }
}
// 输出: [Red,Green,Orange]

ArrayList类其他有用的方法包括:
*contains():如果列表包含指定的元素,则返回true, 否则返回false。
*get(int index):返回列表中指定位置的元素。
*size():返回列表中元素的数量。
*clear():删除列表中所有元素。


提示:ArrayList类与数组一样,索引从0开始。


LinkedList

LinkedList

LinkedList在语法上与ArrayList非常相似。

你可以通过更改对象类型,将ArrayList更改为LinkedList。

import java.util.LinkedList;

public class MyJavaClass {
  public static void main(String[] args) {
    LinkedList<String> c = new LinkedList<String>();
    c.add("Red");
    c.add("Blue");
    c.add("Green");
    c.add("Orange");
    c.remove("Blue");
    System.out.println(c);
  }
}
// 输出 [Red,Green,Orange]

提示:不能为LinkedList指定初始容量。


LinkedList题目

image

LinkedList 与 ArrayList 的区别

LinkedList和ArrayList最明显的区别在于它们存储对象的方式。

ArrayList更适合于存储和访问数据,因为它与普通数组非常相似。

LinkedList更适合操作数据,比如进行大量的插入和删除操作。

除了存储对象之外,LinkedList还存储相邻元素内存地址(或链接)。

它被称为LinkedList,是因为每个元素都包含到相邻元素的链接。

你可以使用增强型的for循环遍历其元素。

LinkedList<String> c = new LinkedList<String>();
c.add("Red");
c.add("Blue");
c.add("Green");
c.add("Orange");
c.remove("Blue");

for(String s:c) {
  System.out.println(s);
}

/* 输出:
Red
Green
Orange
 */

提示:当你需要快速访问数据时,请使用ArrayList;当需要进行大量的插入和删除操作时,请使用LinkedList。


HashMap

HashMap

数组和列表将元素存储为有序集合,每个元素都有一个整数索引。

HashMap用于将数据集合存储为键和值对。一个对象被用作另一个对象(值)的键(索引)。

put,remove和get方法用于添加,删除和访问HashMap中的值。

下面是一个例子:

import java.util.HashMap;
public class MyJavaClass {
  public static void main(String[] args) {
    HashMap<String, Integer> points = new HashMap<String, Integer>();
    points.put("Shuter", 90);
    points.put("Loen", 85);
    points.put("Lu", 80);
    System.out.println(points.get("Loen")); 
  }
}

// 输出 85

我们创建了一个HashMap,其中的字符串作为键,整数作为其值。


提示:使用get方法和相应的键来访问HashMap元素。


HashMap题目

image

HashMap

一个HashMap不能包含重复的键。使用已存在的键添加新项目会覆盖旧元素。

HashMap类提供了containsKey和containsValue方法,用于确定是否存在指定的键或值。

如果尝试获取映射中不存在的值,则返回null值。

import java.util.HashMap;
public class MyJavaClass {
  public static void main(String[] args) {
    HashMap<String, Integer> points = new HashMap<String, Integer>();
    points.put("Shuter", 90);
    System.out.println(points.containsKey("Shuter")); 
  }
}

运行结果:

true
null

提示:null是表示缺少值的特殊类型。


HashMap题目

image

Set

Set (集合)

Set是不能包含重复元素的集合。它模拟数学集抽象。

Set的一个实现是HashSet类。

下面是一个例子:

import java.util.HashSet;

public class MyJavaClass {
  public static void main(String[] args) {
    HashSet<String> set = new HashSet<String>();
    set.add("A");
    set.add("B");
    set.add("C");
    set.add("A");
    System.out.println(set);
  }
}

//  输出: [A, B, C]


提示:你可以使用size()方法获取HashSet中元素的数量,例如set.size()。


Set题目

image

LinkedHashSet

HashSet类不会自动保留添加元素的顺序。若要对元素进行排序,请使用LinkedHashSet,它按照它们插入的顺序来维护集合元素的链接列表。

什么是哈希?

哈希表通过称为哈希的机制存储信息,其中使用键的信息内容来确定称为哈希码的唯一值。

所以,HashSet中的每个元素都与其唯一的哈希码相关联。


提示:Java中可用的集合类型,包括Set(集)、List(列表)和Map(映射),选择使用哪一个取决于你需要存储和操作的数据。


LinkedHashSet题目

image

排序列表

排序列表

为了处理不同集合类型的数据,Java API提供了一个Collections类,它包含在java.util包中。

最常用的Collections类方法之一是sort(),它对集合类型的元素进行排序。Collections类中的方法是静态的,所以不需要一个Collections对象来调用它们。

下面是一个例子:

import java.util.ArrayList;

import java.util.Collections;

public class MyJavaClass {

  public static void main(String[] args) {

    ArrayList<String> animals = new ArrayList<String>();

    animals.add("dog");

    animals.add("cat");

    animals.add("monkey");

    animals.add("bear");

       

    Collections.sort(animals);

       

    System.out.println(animals);

  }

}

/* 输出:

[bear,cat,dog,monkey]

*/

如你所见,这些元素的输出结果已经按字母顺序排序了。

排序列表题目

image

排序列表

你可以在不同类型的列表上调用sort()方法,如Integer。

import java.util.ArrayList;
import java.util.Collections;

public class MyJavaClass {
  public static void main(String[] args) {
    ArrayList<Integer> nums = new ArrayList<Integer>();
    nums.add(12);
    nums.add(17);
    nums.add(30);
    nums.add(33);
    nums.add(7);

    Collections.sort(nums);
    System.out.println(nums);
  }
}

/* 输出:
[7,12,17,30,33]
*/

Collections类中其他有用的方法:

*max(Collection c):返回由自然顺序决定的c中的最大元素。
*min(Collection c):返回由自然顺序决定的c中的最小元素。
*reverse(List list): 反转列表中的序列。
*shuffle(List list): 将列表中的元素随机排序。

排序列表题目

image

迭代器(Iterators)

迭代器(Iterators)

迭代器是一个能够循环访问,获取或删除元素的对象。

在通过迭代器访问集合之前,你必须先获得一个集合。每个集合类都提供了一个iterator()方法,它将一个迭代器返回到集合的开始处。通过使用这个迭代器对象,你可以访问集合中的每个元素,一次一个元素。

Iterator类提供了以下方法:

hasNext():检查序列中是否还有元素。如果还有元素,则返回true;否则,它返回false。

next():获得序列中的下一个元素。

remove():将迭代器新返回的元素删除。

Iterator类必须从java.util包中导入。

下面是一个例子:

import java.util.Iterator;
import java.util.LinkedList;

public class MyJavaClass {
  public static void main(String[] args) {
  LinkedList<String> animals = new LinkedList<String>();
  animals.add("dog");
  animals.add("cat");
  animals.add("monkey");
  animals.add("bear");

  Iterator<String> it = animals.iterator();
  String value = it.next();
  System.out.println(value);
  }
}

//输出 "dog"

提示:it.next() 返回列表中的第一个元素,然后将迭代器移动到下一个元素。每次调用it.next() 时,迭代器都会移到列表的下一个元素。


迭代器题目

image

迭代器(Iterators)

通常,迭代器被用在循环中。在循环的每次迭代中,都可以访问相应的列表元素。

下面是一个例子:

import java.util.Iterator;
import java.util.LinkedList;

public class MyJavaClass {
  public static void main(String[] args) {
    LinkedList<String> animals = new LinkedList<String>();
    animals.add("dog");
    animals.add("cat");
    animals.add("monkey");
    animals.add("bear");
     
    Iterator<String> it = animals.iterator();
    while(it.hasNext()) {
      String value = it.next();
      System.out.println(value);   
     }
  }
}

/* 输出
dog
cat
monkey
bear
*/

在这里,while循环决定迭代器是否有附加元素,打印元素的值,并将迭代器推进到下一个元素。

迭代器While循环题目

image

使用文件

使用文件

java.io 包中包含一个File类,允许你使用文件。

首先,创建一个File对象,并在构造函数中指定文件的路径。

import java.io.File;
...
File file = new File("D:\\data\\input-file.txt");

使用exists()方法,你可以确定文件是否存在。

import java.io.File;

public class MyJavaClass {
  public static void main(String[] args) {
    File x = new File("D:\\edong\\w3cschool.txt");
    if(x.exists()) {
     System.out.println(x.getName() +  "exists!");
    }
    else { 
     System.out.println("The file does not exist");
    }
  }
}

上面的代码打印一条消息,指出文件是否存在于指定的路径。


提示:getName()方法返回文件的名称。请注意,我们在路径中使用双反斜杠,因为一个反斜杠应该在字符串路径中转义。


使用文件题目

image

读取文件

读取文件

文件对于存储和检索数据非常有用,并且有许多方法可以从文件中读取。

最简单的方法之一是使用java.util包中的Scanner类

Scanner类的构造函数可以将File对象作为输入。

要读取路径“D:\edong\tly.txt”中的文本文件的内容,我们需要创建一个具有相应路径的File对象,并将其传递给Scanner对象。

try {
  File x = new File("D:\\edong\\tly.txt");
  Scanner sc = new Scanner(x);      
}
 catch (FileNotFoundException e) {

}

在代码中,我们用try/catch块包围了代码,因为该文件可能不存在。

image

读取文件

我们可以使用Scanner对象的next()方法来读取文件的内容。

try {
  File x = new File("D:\\edong\\tly.txt");
  Scanner sc = new Scanner(x);
  while(sc.hasNext()) {
    System.out.println(sc.next());
  }
  sc.close();
} catch (FileNotFoundException e) {
  System.out.println("Error");
}

文件的内容逐字输出,因为next() 方法分别返回每个单词。


提示:关闭文件时总是一个好习惯。一种方法是使用Scanner的close()方法。


读取文件题目

image

创建和写入文件

创建文件

Formatter是java.util包中另一个有用的类,用于创建内容并将其写入文件。

下面是一个例子:

import java.util.Formatter;

public class MyJavaClass {
  public static void main(String[] args) {
  try {
    Formatter f = new Formatter("D:\\edong\\w3cschool.txt");
  } catch (Exception e) {
      System.out.println("Error");
  }
  }
}

这将在指定的路径中创建一个空文件。如果该文件已经存在,这将覆盖它。

同样,你需要用try/catch块来包围代码,因为操作可能会失败。

创建文件题目

image

写入文件

一旦创建了文件,就可以使用相同的Formatter对象的format()方法向其中写入内容。

下面是一个例子:

import java.util.Formatter;

public class MyJavaClass {
  public static void main(String[] args) {
  try {
    Formatter f = new Formatter("C:\\edong\\w3cschool.txt");
    f.format("%s %s %s","1","Loen","Wang \r\n");
    f.format("%s %s %s","2","Lu","Lin");
    f.close();    
  } catch (Exception e) {
    System.out.println("Error");
  }
  }
}

format()方法根据其第一个参数来设置参数的格式。

%s表示一个字符串,并在格式之后被get的第一个参数替换。第二个%s被下一个替换,依此类推。所以,格式%s%s%s表示三个用空格分隔的字符串。

注意:\r\n是Windows中的换行符号。

上面的代码创建一个包含以下内容的文件:

1 Loen Wang 
2 Lu Lin

提示:完成写入文件后,不要忘记关闭文件。


写入文件题目

image

异常、列表、线程和文件小节训练

image
image
image
image
image
image
image

posted @ 2021-08-28 20:06  Stéphane  阅读(67)  评论(0)    收藏  举报