java Note
<> Data type
long数据类型后要加L
long tel = 13929068827L;
float数据类型后面要加f
float height = 183.1f;
<> Operator
x++:先执行操作再自增
++x:先自增再执行操作
public static void main(String[] args) {
int x = 10;
int y = x++; // y = 10, x = 11
int z = ++y; // y = 11, z = 11
System.out.println("x="+x);
System.out.println("y="+y);
System.out.println("z="+z);
System.out.println("----------------------");
int a = 3;
// 4 + 4 + 5*10
int b = (++a)+(a++)+(a*10);
System.out.println("a="+a);
System.out.println("b="+b);
}
赋值运算符
基本赋值运算符
=:将等号右侧数据赋值给左边的变量
拓展赋值运算符
+=:将符号左右两边的数据做加法运算,再将结果赋值给左边-=*=/=%=
:warning:拓展赋值运算符,内部自带强转效果。
/*
short s = 1;
s = (short)(S+1);
<=>
short s = 1;
s += 1;
*/
public static void main(String[] args) {
int num = 10;
num += 20; // num = num + 20
System.out.println(num);
System.out.println("-------------------");
short s = 1;
s += 1; // s = (short)(s+1);
System.out.println(s);
System.out.println("-------------------");
double a = 12.3;
int b = 10;
b += a; // b = (int)(b+a);
System.out.println(b); // 22
}
逻辑运算符
- 用于连接
boolean类型的表达式或者值 - 整合多个条件,作为一段整体的逻辑
分类
&:与|:或!:非^:异或,不同为true,相同为false
短路逻辑运算符
&:没有短路效果,无论左边true还是false,右边都要继续判断&&:具有短路效果,如果左边为false,右边就不判断了;若果左边为true,右边要继续判断||:具有短路效果,如果左边为true,右边就不判断了;若果左边为false,右边要继续判断
public static void main(String[] args) {
int x = 3;
int y = 4;
// false & false
boolean result = ++x > 5 & y-- < 4;
System.out.println(x); // 4
System.out.println(y); // 3
System.out.println(result); // false
System.out.println("--------------------");
int x2 = 3;
int y2 = 4;
// false && 不用判断(执行)
boolean result2 = ++x2 > 5 && y2-- < 4;
System.out.println(x2); // 4
System.out.println(y2); // 4
System.out.println(result2);// false
}
运算符优先级
&&的优先级要大于||
三元运算符(三目运算符)
格式:
condition? value1 : value2;
执行流程:
- 执行判断条件, 看其返回结果是
true还是false true的话返回value1false的话返回value2
public static void main(String[] args) {
int a = 10;
int b = 20;
int max = a > b ? a : b;
System.out.println(max);
}
<> Scanner
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int age = sc.nextInt();
System.out.println("Your input is " + age);
}
}
Scanner的部分成员方法:
String next():遇到空格/tab就不再录入String nextLine():遇到enter就不再录入
<> Type conversion
隐式转换
将取值范围小的数据或变量,给取值范围大的变量赋值,可以直接赋值。
范围从小到大:
byte -> short \
-> int -> long -> float -> double
char /
float虽然占用4个字节,但取值范围比8个字节的long更大。
- 小数的二进制储存形式更加节省内存
public static void main(String[] args) {
int a = 10;
double b = a;
System.out.println(a); // 10
System.out.println(b); // 10.0
System.out.println("-------------------");
long num1 = 123L;
float num2 = num1;
System.out.println(num2);
}
强制转换
将取值范围大的数据或变量,给取值范围小的变量赋值,不允许直接赋值,需要加入强转。
:warning:强制转换有可能会出现精度损失
public static void main(String[] args) {
double a = 12.3;
int b = (int) a;
System.out.println(b); // 12
System.out.println("------------------");
int c = 10;
byte d = (byte) c;
System.out.println(d); // 10
System.out.println("------------------");
int num1 = 130;
byte num2 = (byte) num1;
System.out.println(num2); // -126, 由于2's complement的byte取值范围为-128~127, 130溢出到-126
}
常量优化机制
/*
类型转换面试题:下列代码是否存在错误, 如果有, 请指出并改正.
byte b1 = 3;
byte b2 = 4;
byte b3 = b1 + b2;
错误原因:
b1和b2是两个byte类型, 在运算的时候, 会提升为int类型,
提升之后, 两个int类型运算结果还是int.
将int类型的结果赋值给byte类型的变量属于大给小, 不能直接给.
byte b1 = 3;
byte b2 = 4;
int b3 = b1+b2;
or
byte b3 = (byte)(b1+b2);
System.out.println(b3);
--------------------------------------------------------
byte b = 3+4;
Java存在常量优化机制:在编译的时候(javac)会将3和4这两个字面量进行计算.
产生的字节码文件:byte b = 7;
*/
<> Method
一段具有独立功能的代码块,不调用就不执行。
Advantage:
- 可以将原本挤在一起的臃肿代码按照功能做分类管理
- 提高代码的复用性
定义格式:
public static void methodName (){
method body (code);
}
调用格式:
methodName();
方法重载Overload
在同一个类中,定义多个同名的方法,但每个方法含有不同类型、个数或者顺序的参数,这些同名的方法构成重载关系。
:warning:识别方法之间是否重载关系,只看方法名和参数,和返回值以及返回值的类型无关
public class OverloadDemo {
public static void main(String[] args) {
}
public static void method(double a, double b) {
}
public static void method(int a, int b) {
}
public static void method(int a, int b, int c) {
}
public static void method(int a, double b) {
}
public static void method(double a, int b) {
}
}
<> Switch
switch语句格式:
switch(将要匹配的值){
case value1:
body1;
break;
case value2:
body2;
break;
...
default:
body_n+1;
break;
}
:warning:
case后面的值不能重复case后面的值只能是字面量,不能是变量switch()中能接收的类型:- 基本数据类型:
byte/short/char/int - 引用数据类型:
jdk5版本开始可以是枚举,jdk7版本开始可以是String
- 基本数据类型:
switch的穿透现象,见example2
example1 - switch实例
键盘输入一个整数,根据录入的数值,打印相应的星期。
public static void switchTest1() {
Scanner sc = new Scanner(System.in);
System.out.println("Please input an integer");
int week = sc.nextInt();
switch (week){
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
default:
System.out.println("Error");
break;
}
}
example2 - switch的穿透现象
switch的穿透现象,在这个实例中,当case 1的break省略后,程序会首先执行完case 1的代码,然后穿透到case 2,碰到break才停止运行。
public static void switchTest3() {
int week = 1;
switch (week) {
case 1:
System.out.println("Monday");
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Error");
break;
}
}
example3 - 利用穿透现象的优化
键盘录入一个数值,1~5输出工作日,6~7输出休息日。比较switchTest4_before和switchTest4_after,优化标准代码。
switchTest4_before
public static void switchTest4_before() {
Scanner sc = new Scanner(System.in);
System.out.println("Please input an integer");
int week = sc.nextInt();
switch (week) {
case 1:
System.out.println("Work day");
break;
case 2:
System.out.println("Work day");
break;
case 3:
System.out.println("Work day");
break;
case 4:
System.out.println("Work day");
break;
case 5:
System.out.println("Work day");
break;
case 6:
System.out.println("Week-end");
break;
case 7:
System.out.println("Week-end");
break;
default:
System.out.println("Error");
break;
}
}
switchTest4_after
public static void switchTest4_after() {
Scanner sc = new Scanner(System.in);
System.out.println("Please input an integer");
int week = sc.nextInt();
switch (week) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("Work day");
break;
case 6:
case 7:
System.out.println("Week-end");
break;
default:
System.out.println("Error");
break;
}
}
jdk14以后的版本优化
从jdk14开始,case后面允许编写多个数据,多个数据中间使用逗号分隔。
public static void switchTest5() {
Scanner sc = new Scanner(System.in);
System.out.println("Please input an integer");
int week = sc.nextInt();
switch (week) {
case 1, 2, 3, 4, 5:
System.out.println("Work day");
break;
case 6, 7:
System.out.println("Week-end");
break;
default:
System.out.println("Error");
break;
}
}
代码可以进一步优化,用符号->,并且把break删去。
public static void switchTest6() {
Scanner sc = new Scanner(System.in);
System.out.println("Please input an integer");
int week = sc.nextInt();
switch (week) {
case 1, 2, 3, 4, 5 -> System.out.println("Work day");
case 6, 7 -> System.out.println("Week-end");
default -> System.out.println("Error");
}
}
与if-else if-else语句的比较
if语句:适用于范围性的判断switch语句:适用于固定值的匹配
<> For
for循环语句格式:
for(initialisation; condition; control){
loop body;
}
执行流程
- 执行初始化语句,在整个循环过程中,只执行一次
- 执行判断条件,看其返回结果是
true/falsefalse:循环结束true:执行:three:
- 执行循环体语句
- 执行条件控制语句
- 回到:two:继续
public static void forTest1() {
for (int i = 1; i <= 3; i++) {
}
}
:warning:
- for循环
{}中定义的变量,在每一轮循环结束后,都会从内存中释放 - for循环
()中定义的变量,在整个循环结束后,会从内存中释放
public static void forTest2() {
for (int i = 0; i < 5; i++) {
int num = 10;
System.out.println("...");
}
System.out.println(num); // 此处for中的num变量在循环结束后已经从内存中释放,程序将会报错
System.out.println(i); // 此处的i变量同样从内存中释放了,程序将会报错
}
<> While
while循环格式:
initialisation;
while(condition) {
loop body;
control;
}
<> Do...while
do...while循环格式:
initialisation;
do {
loop body;
control;
} while (condition);
<> Control
跳转控制:给循环起名,break可以直接对应到该名位置
public static void iniMenu() {
Scanner sc = new Scanner(System.in);
lo: // 标号:给循环起名字,break可以选择直接跳到这一层
while (true) {
System.out.println("请输入您的选择:1. 添加学生 2. 删除学生 3. 修改学生 4. 查看学生 5. 退出");
int choice = sc.nextInt();
switch (choice) {
case 1:
System.out.println("添加学生逻辑执行...");
break;
case 2:
System.out.println("删除学生逻辑执行...");
break;
case 3:
System.out.println("修改学生逻辑执行...");
break;
case 4:
System.out.println("查看学生逻辑执行...");
break;
case 5:
System.out.println("感谢您的使用,再见");
break lo; // 跳转到lo位置
default:
System.out.println("Error");
break;
}
}
}
<> Random
Random产生随机数,范围是。
import java.util.Random;
public static void randomTest() {
Random r = new Random();
// 产生从20到80之间的随机数
int num = r.nextInt(61)+20;
}
<> Array
数组声明
dataType[] arrName;ordataType arrName[];
public static void arrayTest1() {
int[] array;
}
数组静态初始化
- 完整格式:
dataType[] arrName = new dataType[]{element1, element2, element3, ...}; - 简化格式:
dataType[] arrName = {element1, element2, element3, ...};
下面的实例中arr1输出结果为[I@4617c264,其中:
@:分隔符[:当前内存空间为数组类型I:当前数组类型为int4617c264:数组内存地址
public static void arrayTest2() {
int[] arr1 = new int[]{11,22,33};
double[] arr2 = {11.1,22.2,33.3};
System.out.println(arr1); // [I@4617c264
System.out.println(arr2); // [D@36baf30c
}
数组元素访问
访问数组中某一个元素:arr[index]
public static void arrayTest() {
int[] arr = {11,22,33,44,55};
// 取出元素22
System.out.println(arr[1]);
// 修改数组中第三个元素为66
arr[2] = 66;
System.out.println(arr[2]);
}
数组长度
arrName.length表示数组长度。
数组遍历
数组的for遍历快捷键:arrName.fori。
public static void arrayTest2() {
int[] arr = {1,2,3,4,5,6,7,8};
System.out.println(arr.length);
for (int i = 0; i < arr.length; i++) {
}
}
数组动态初始化
数组动态初始化:在初始化时,只需要指定数组的长度,系统会自动分配初始值。
格式:dataType[] arrName = new dataType[length]。
默认值分类:
-
int:0 -
double:0.0 -
boolean:false -
char:'\u0000'(unicode字符都以\u开头,后接四位十六进制,这里的0000表示空白字符) -
引用数据类型(数组/类/接口):
null
public static void arrayTest() {
int[] arr1 = new int[3];
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]); // 输出:0
// 0
// 0
}
// String是字符串类,属于引用数据类型,默认值为null
String[] arr2 = new String[3];
for (int i = 0; i < arr2.length; i++) { // 输出:null
System.out.println(arr2[i]); // null
} // null
}
<> 2D Array
二维数组静态初始化
格式:
-
标准:
dataType[][] arrName = new dataType[][]{ {element1,element2}, {element1,element2} }; -
简化:
dataType[][] arrName = { {element1,element2}, {element1,element2} };
:warning::二维数组存储的是一维数组的地址值。
public static void main(String[] args) {
// 二维数组静态初始化
// dataType[][] arrName = new dataType[][]{ {element1,element2}, {element1,element2} };
// dataType[][] arrName = { {element1,element2}, {element1,element2} };
int[][] arr = {
{1,2,3},
{4,5,6}
};
System.out.println(arr); // [[I@4617c264
System.out.println(arr[0]); // [I@36baf30c
System.out.println(arr[1]); // [I@7a81197d
// 二维数组元素访问
System.out.println(arr[0][1]); // 2
System.out.println(arr[1][2]); // 6
}
二维数组遍历
-
第一层快捷键:
arr.fori -
第二层快捷键:
arr[i].fori,再将遍历索引i改成j
public static void main(String[] args) {
int[][] arr = {
{1,2,3},
{4,5,6}
};
/*
二维数组遍历
第一层快捷键arr.fori
第二层快捷键arr[i].fori,再将i改成j
*/
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
二维数组动态初始化
格式:dataType[][] arrName = new dataType[length_row][length_col];
private static void arrayTest1() {
int[][] arr = new int[2][3];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
:warning::可以将提前创建好的一维数组直接存入二维数组。
public static void main(String[] args) {
int[] arr1 = {11,22,33};
int[] arr2 = {44,55,66};
// 将提前创建好的一维数组直接存入二维数组
int[][] arr = new int[2][3];
arr[0] = arr1;
arr[1] = arr2;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
<> StringTokenizer
StringTokenizer属于java.util包,用于分隔字符串。
常用方法
-
boolean hasMoreTokens()返回是否还有分隔符 -
String nextToken返回从当前位置到下一个分隔符的字符串
<> Exception
空指针异常 NullPointerException
当引用数据类型变量被赋值为null后,其跟堆内存的连接被切断,此时想根据地址去访问堆内存的数据,就会出现空指针异常。
public static void main(String[] args) {
int[] arr = {1,2,3};
arr = null;
System.out.println(arr[0]);
}
Output:
Exception in thread "main" java.lang.NullPointerException: Cannot load from int array because "arr" is null
at exception.NullPointerExceptionDemo.main(NullPointerExceptionDemo.java:13)
<> Object Oriented Programming (OOP)
类Class
-
类
class:一组相关属性和行为的集合,是对象object的设计图 -
对象
object:根据设计图(类),创建出来的实体
类的组成:
-
属性:成员变量
-
行为:成员方法,需要去掉
static关键字
public class Student {
// 属性
String name = "albert";
int age = 24;
// 行为(方法)
public void study() {
System.out.println("Studying...");
}
public void eat() {
System.out.println("Eating...");
}
}
对象Object
-
创建对象的格式:
className objectName = new className(); -
使用对象的成员变量:
objectName.memberVar -
使用对象的成员方法:
objectName.memberMethod
:warning::打印对象名,可以看到对象的内存地址(全类名=包名.类名)
:warning::成员变量就算没有赋值,也可以直接使用,使用的是变量的默认值
public static void main(String[] args) {
Student stu1 = new Student();
System.out.println(stu1); // oop.Student@36baf30c
// 包名.类名@内存地址
System.out.println(stu1.name);
System.out.println(stu1.age);
stu1.study();
stu1.eat();
System.out.println("---------------------");
Student stu2 = new Student();
System.out.println(stu2); // oop.Student@7a81197d
System.out.println(stu2.name);
System.out.println(stu2.age);
stu2.study();
stu2.eat();
}
This
当成员变量与局部变量重名时,java采用就近原则。如果一定要使用成员变量的情况,需要使用this关键字进行区分。
this关键字的作用:
-
调用本类成员变量:
this.memberVar -
调用本类成员方法:
this.memberMethod
this关键字省略规则:
-
对于本类成员变量:如果该方法中没有重名变量,
this.才可以省略 -
对于本类成员方法:没有前提条件,
this.可以直接省略
this本质:代表当前类对象的引用(地址)
一个对象的this代表的就是该对象的地址。
public class Student {
String name;
public void sayHello(String name) {
System.out.println("local variable: "+name); // local variable: Betty
System.out.println("member variable: "+this.name); // member variable: Albert
this.method();
}
public void method() {
System.out.println("method...");
}
public void print() {
System.out.println("print keyword this: "+this); // mthis.Student@7a81197d
}
}
public static void main(String[] args) {
Student stu1 = new Student();
stu1.name = "Albert";
stu1.sayHello("Betty");
System.out.println("-----------------");
System.out.println(stu1); // mthis.Student@7a81197d
stu1.print(); // print keyword this: mthis.Student@7a81197d
Student stu2 = new Student();
System.out.println(stu2); // mthis.Student@5ca881b5
stu2.print(); // print keyword this: mthis.Student@5ca881b5
}
Constructor
构造器:创建对象时要执行的方法,标准形式包括一个有参构造和无参构造。
格式:
-
方法名与类名相同,大小写一致
-
没有返回值类型,没有
void -
没有具体的返回值,不能有
return语句
public class Student {
String name;
int age;
// 有参构造
public Student(String name, int age) {
System.out.println("this is constructor of class Student");
this.name = name;
this.age = age;
}
// 无参构造
public Student() {
}
}
constructor的执行时机:
-
在创建对象的时候,被调用执行
-
每创建一次对象,就会执行一次构造方法
constructor的作用:
-
本质作用:创建对象
-
结合执行时机:在创建对象的时候,给对象中的数据(成员对象)初始化,类似
python的__init__()
:warning:
- 一个类中,如果没有编写构造方法,系统将会提供一个默认的且无参数的构造方法
- 一个类中,如果手动编写了构造方法,系统将不会提供默认的无参构造
- 建议:编写类的时候,无参构造,有参构造都手动给出
- 构造方法不允许手动调用
- 如:
stu3.Student();
- 如:
public static void main(String[] args) {
Student stu1 = new Student("Albert",24);
Student stu2 = new Student("Betty",23);
Student stu3 = new Student("Cat",22);
}
Permissions
权限修饰符:
-
private:同一个类中 -
(default):默认权限,同一个类中,同一个包中 -
protected:同一个类中,同一个包中,不同包的子类 -
public:任意位置访问
public class Student {
private int age;
// int age;
public void show() {
System.out.println("show...");
}
}
public static void main(String[] args) {
Student stu = new Student();
stu.age = 23; // 由于age在Student内是private,类的外部无法访问,此句将报错
}
Encapsulation
封装:
-
将成员变量私有化
private(保证数据的安全性) -
针对私有的成员变量,提供对应的
setXXX和getXXX方法,中间加入数据合理性判断 -
设计规范:合理隐藏,合理暴露
public class Student {
private int age;
public void setAge(int age) {
if (age >= 1 && age <= 120) {
this.age = age;
} else {
System.out.println("the age input is out of range");
}
}
public int getAge() {
return this.age;
}
}
public static void main(String[] args) {
Student stu = new Student();
stu.setAge(23);
stu.setAge(-23);
System.out.println(stu.getAge());
}
javabean
-
成员变量私有化
-
无参,带参构造方法
-
对于私有成员变量,提供对应的
setXXX和getXXX方法
:warning::实体类只负责数据的存取,对数据的处理交由其他类来完成,以实现数据和数据业务处理相分离。
生成器:
generator:快捷键command+N,选择constructor/setter and getter/toString
Ptg plugin:快捷键command+shift+,,一键生成constructor+setter+getter+toString
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
实例
在该实例中,实体类只负责数据的存取,对数据的处理交由其他类来完成,实现了数据和数据业务处理相分离。
package domain;
public class Movie {
private int id;
private String title;
private String time;
private double score;
private String region;
private String genre;
private String director;
private String starring;
public Movie() {
}
public Movie(int id, String title, String time, double score, String region, String genre, String director, String starring) {
this.id = id;
this.title = title;
this.time = time;
this.score = score;
this.region = region;
this.genre = genre;
this.director = director;
this.starring = starring;
}
/**
* 获取
* @return id
*/
public int getId() {
return id;
}
/**
* 设置
* @param id
*/
public void setId(int id) {
this.id = id;
}
/**
* 获取
* @return title
*/
public String getTitle() {
return title;
}
/**
* 设置
* @param title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* 获取
* @return time
*/
public String getTime() {
return time;
}
/**
* 设置
* @param time
*/
public void setTime(String time) {
this.time = time;
}
/**
* 获取
* @return score
*/
public double getScore() {
return score;
}
/**
* 设置
* @param score
*/
public void setScore(double score) {
this.score = score;
}
/**
* 获取
* @return region
*/
public String getRegion() {
return region;
}
/**
* 设置
* @param region
*/
public void setRegion(String region) {
this.region = region;
}
/**
* 获取
* @return genre
*/
public String getGenre() {
return genre;
}
/**
* 设置
* @param genre
*/
public void setGenre(String genre) {
this.genre = genre;
}
/**
* 获取
* @return director
*/
public String getDirector() {
return director;
}
/**
* 设置
* @param director
*/
public void setDirector(String director) {
this.director = director;
}
/**
* 获取
* @return starring
*/
public String getStarring() {
return starring;
}
/**
* 设置
* @param starring
*/
public void setStarring(String starring) {
this.starring = starring;
}
}
package service;
import domain.Movie;
import java.util.Scanner;
public class MovieService {
private Movie[] movies;
private Scanner sc = new Scanner(System.in);
public MovieService(Movie[] movies) {
this.movies = movies;
}
/**
* 启动电影信息管理系统
*/
public void start() {
lo:
while (true) {
System.out.println("----------Movie Info System----------");
System.out.println("Please input your choice:");
System.out.println("1: enquire all movie info");
System.out.println("2: enquire movie info via id");
System.out.println("3: exit");
int choice = sc.nextInt();
switch (choice) {
case 1:
queryMovieInfos();
break;
case 2:
queryMovieInfoById();
break;
case 3:
System.out.println("Exit");
break lo;
default:
System.out.println("Error, please check your input");
break;
}
}
}
/**
* 根据电影编号,查询电影详情信息
*/
private void queryMovieInfoById() {
// 1. 键盘录入用户输入的编号
System.out.println("Please input the query movie id:");
int id = sc.nextInt();
// 2. 遍历数组,从数组中查询电影信息
for (int i = 0; i < movies.length; i++) {
Movie movie = movies[i];
if (id == movie.getId()) {
// 3. 将找到的电影信息,打印在控制台
System.out.println(movie.getId()+"---"+movie.getTitle()+"---"+movie.getTime()
+"---"+movie.getScore()+"---"+movie.getRegion()+"---"+movie.getGenre()
+"---"+movie.getDirector()+"---"+movie.getStarring());
return;
}
}
// 代码如果走到这里,说明没找到
System.out.println("The input id does not exist, please check.");
}
/**
* 展示系统中全部的电影(名称,评分)
*/
private void queryMovieInfos() {
// 1. 遍历数组,取出每一个电影对象
for (int i = 0; i < movies.length; i++) {
Movie movie = movies[i];
// System.out.println(movie); 打印对象名,会看到内存地址
// 2. 通过电影对象,调用内部getXXX方法,获取信息并打印
System.out.println(movie.getTitle()+"---"+movie.getScore());
}
}
}
package service;
import domain.Movie;
public class Test {
public static void main(String[] args) {
Movie movie1 = new Movie(1, "Love letter", "1995", 7.9, "Japan", "Drama", "Shunji Iwai", "Miho Nakayama");
Movie movie2 = new Movie(2, "Inception", "2010", 8.8, "US", "Sci-Fi", "Christopher Nolan", "Leonardo DiCaprio");
Movie movie3 = new Movie(3, "The legend of 1900", "1998", 8.0, "Italy", "Music", "Giuseppe Tornatore", "Tim Roth");
Movie[] movies = {movie1,movie2,movie3};
MovieService movieService = new MovieService(movies);
movieService.start();
}
}
<> String类
String类的特点
- Java中所有双引号字符串,都是
String这个类的对象 - 字符串一旦被创建,就不可更改。如果想要更改,只能使用新的对象,来替换,而旧的
String对象本身并没有发生改变。 String字符串虽然不可改变,但可以共享- 字符串常量池
StringTable:当使用双引号创建字符串对象时,会检查常量池中是否存在该数据- 不存在:创建
- 存在:复用
- 字符串常量池所处位置:
jdk7版本之前:在方法区jdk7版本开始:被挪到了堆内存中
- 字符串常量池
public static void main(String[] args) {
String s = "abc";
System.out.println(s.toUpperCase());
System.out.println("helloworld".toUpperCase());
System.out.println("-----------------------------");
String s1 = "abc";
s1 = "def";
System.out.println(s1);
System.out.println("-----------------------------");
String s2 = "abc";
String s3 = "abc";
System.out.println(s2 == s3); // true
}
构造方法
String类常见构造方法:
public String():创建一个空白字符串,里面不含任何内容public String(char[] chs):根据传入的字符数组,创建字符串对象public String(String original):根据传入字符串来创建字符串对象
public static void main(String[] args) {
// public String():创建一个空白字符串,里面不含任何内容
String s1 = new String();
System.out.println(s1);
// public String(char[] chs):根据传入的字符数组,创建字符串对象
char[] chs = {'a','b','c'};
String s2 = new String(chs);
System.out.println(s2); // abc
// public String(String original):根据传入字符串来创建字符串对象
String s3 = new String("abc");
System.out.println(s3); // abc
}
String所处地址1
s1和s2共用StringTable内的"abc",地址相同。
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); // true
}
String所处地址2
s1用双引号直接创建,记录StringTable内"abc"的地址s2通过new对象创建,记录的是堆内存中对象的地址,该过程创建了两个字符串对象- 两者内存中的位置不同
public static void main(String[] args) {
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s1 == s2); // false
}
String所处地址3
字符串的加法会在堆内存创建一个StringBuilder对象,完成"ab"和"c"的拼接,再通过成员方法toString(),将其转换成堆内存中一个String对象,内容是"abc",s3记录该对象地址,因此和s1地址不同。
public static void main(String[] args) {
String s1 = "abc";
String s2 = "ab";
String s3 = s2 + "c";
System.out.println(s1 == s3); // false
}
String所处地址4
s2是三个字符串常量拼接,java有常量优化机制,在字节码文件中已经完成拼接,因此s2也记录StringTable内的"abc"地址,和s1相同。
public static void main(String[] args) {
String s1 = "abc";
String s2 = "a" + "b" + "c";
System.out.println(s1 == s2); // true
}
equals/equalsIgnoreCase
String类中用于比较的方法:
-
public boolean equals(Object anObject)将此字符串与指定对象比较 -
public boolean equalsIgnoreCase(String anotherString)将此String与另一个String比较,不考虑大小写
public static void main(String[] args) {
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true
System.out.println("-------------------------");
String s3 = "abc";
String s4 = "ABC";
System.out.println(s3.equals(s4)); // false
System.out.println(s3.equalsIgnoreCase(s4)); // true
}
toCharArray/charAt/length
String类用于遍历的方法:
-
public char[] toCharArray()将此字符串转换为一个新的字符数组 -
public char charAt(int index)返回指定索引处的char值 -
public int length()返回此字符串的长度
/**
* 字符串的第一种遍历方式,比第二种效率更高
*/
private static void print1() {
String s = "helloworld";
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
}
/**
* 字符串的第二种遍历方式
*/
private static void print2() {
String s = "helloworld";
char c = s.charAt(2);
System.out.println(c);
for (int i = 0; i < s.length(); i++) {
System.out.println(s.charAt(i));
}
}
substring
String类的切片方法:
-
public String substring(int beginIndex)根据传入的索引开始做切片,截取到字符串的末尾 -
public String substring(int beginIndex, int endIndex)根据传入的开始和结束索引,截取字符串,包含头不包含尾
:warning::截取出来的内容作为新的字符串返回,不要忘记找变量接收
private static void slide1() {
String s = "helloworld";
System.out.println(s.substring(5));
}
private static void slide2() {
String s = "helloworld";
System.out.println(s.substring(0,5));
}
replace
String类的替换方法:
public String replace(CharSequence target, CharSequence replacement):target:旧值replacement:新值
public static void main(String[] args) {
String s = "helloworld";
String result = s.replace("hello", "goodbye");
System.out.println(result); // goodbyeworld
}
split
String类的切割方法:
public String[] split(String regex):根据传入的字符串作为规则,切割当前字符串
:warning::建议先正常指定切割规则,后来发现没有得到自己要的效果,就可以尝试在规则前面加上"\\"
public static void main(String[] args) {
String s = "192,168,1,1";
String[] sArr = s.split(",");
for (int i = 0; i < sArr.length; i++) {
System.out.println(sArr[i]);
}
System.out.println("----------------------");
String s1 = "192.168.1.1";
// "."可以代表任意字符,用该规则进行切割得不到正确的结果,需要变成"\\."
String[] sArr1 = s1.split(".");
System.out.println(sArr1.length);
}
<> StringBuilder类
StringBuilder作用
StringBuilder的作用:提高字符串的操作效率
public static void main(String[] args) {
long start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 100000; i++) {
sb.append(i);
}
System.out.println(sb);
long end = System.currentTimeMillis();
System.out.println(end - start); // 7 ms
}
private static void method1() {
// 获取1970年1月1日0时0分0秒到现在所经历过的毫秒值
long start = System.currentTimeMillis();
String s = "";
for (int i = 1; i <= 100000; i++) {
s += i;
}
System.out.println(s);
long end = System.currentTimeMillis();
System.out.println(end - start); // 1292 ms
}
StringBuilder介绍
- 一个可变的字符序列
StringBuilder是字符串缓冲区,相当于一个容器,可以存储任意数据类型,但进入容器后,这些数据都变成字符串
StringBuilder的构造方法
public StringBuilder():创建一个空白的字符串缓冲区,其初始容量为16个字符,容量不够时会自动扩容public StringBuilder(String str):创建一个字符串缓冲区,容器创建好后初始化为参数的内容
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append(100);
sb.append(45.6);
sb.append(false);
sb.append('中');
sb.append("helloworld");
System.out.println(sb); // 10045.6false中helloworld
System.out.println("---------------------");
StringBuilder sb1 = new StringBuilder("abc");
System.out.println(sb1); // abc
}
append/reverse/length/toString
StringBuilder常用成员方法:
-
public StringBuilder append(any):添加数据并返回对象自己 -
public StringBuilder reverse():将缓冲区的内容进行反转 -
public int length():返回长度 -
public String toString():将缓冲区的内容,以String字符串类型返回
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
// 链式编程:调用的方法,如返回的结果是对象,就可以继续向下调用方法
sb.append(1).append(2).append(3);
System.out.println(sb);
System.out.println("------------------");
sb.reverse();
System.out.println(sb);
System.out.println("------------------");
System.out.println(sb.length());
System.out.println("------------------");
String s = sb.toString();
System.out.println(s);
}
Summary
/*
String ---> StringBuilder
String s = "abc";
StringBuilder sb = new StringBuilder(s);
StringBuilder ---> String
String s = sb.toString();
*/
<> ArrayList列表
构造方法
-
ArrayList list = new ArrayList();- 可以添加任意类型的数据
- 但数据不够严谨
-
ArrayList<String> list = new ArrayList<>();<>是泛型,指定了ArrayList里面能装的数据类型,从jdk7开始,new后面的<>会自动匹配前面所指定的数据类型- 泛型中不允许编写基本数据类型,解决方案是使用基本数据类型所对应的包装类
byte ---> Byteshort ---> Shortint ---> Integer ***long ---> Longfloat ---> Floatdouble ---> Doubleboolean ---> Booleanchar ---> Character ***
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(100);
list.add(45.6);
list.add(false);
list.add('a');
list.add("abc");
System.out.println(list); // [100, 45.6, false, a, abc]
System.out.println("------------------");
ArrayList<Double> list1 = new ArrayList<>();
list1.add(11.1);
list1.add(22.2);
list1.add(33.3);
System.out.println(list1); // [11.1, 22.2, 33.3]
}
add
-
public boolean add(E e):将指定的元素添加到此列表的尾部,add返回boolean类型,固定返回true -
public void add(int index, E element):在指定索引位置,添加对应的元素(插队)
private static void addMethod() {
ArrayList<String> list = new ArrayList<>();
boolean b1 = list.add("1");
boolean b2 = list.add("2");
boolean b3 = list.add("3");
System.out.println(b1); // true代表添加成功
System.out.println(b2); // true
System.out.println(b3); // true
System.out.println(list); // ["1", "2", "3"]
System.out.println("---------------------");
list.add(0, "0");
System.out.println(list); // ["0", "1", "2", "3"]
}
remove
-
public E remove(int index):根据索引做删除,返回被删除掉掉元素 -
public boolean remove(Object o):根据元素做删除,返回是否删除成功的状态
private static void removeMethod() {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
String result = list.remove(1);
System.out.println(result); // 2
System.out.println(list); // [1, 3]
System.out.println("-----------------------");
boolean flag1 = list.remove("1");
boolean flag2 = list.remove("4");
System.out.println(flag1); // true
System.out.println(flag2); // false
System.out.println(list); // [3]
}
set
public E set(int index, E element):修改指定索引位置为对应的元素,返回被覆盖掉的元素
private static void updateMethod() {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
String res = list.set(1, "4");
System.out.println(res); // 2 被覆盖的值
System.out.println(list); // [1, 4, 3]
}
attention
:warning::以上方法的返回值通常不做接收
get
-
public E get(int index):根据索引获取集合中的元素 -
public int size():返回集合中元素的个数,即列表的长度
private static void searchMethod() {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
String s = list.get(2); // "3"
System.out.println(s); // 3
System.out.println(list.size()); // 3
}