环境搭建 ✅ 下载 JDK 8/17,添加环境变量 ✅ 下载 IntelliJ IDEA
编写第一个程序(Hello World) 1 2 3 4 5 public class Main { public static void main (String[] args) { System.out.printf("Hello, world!" ); } }
Java 运行机制 执行流程
编写.java文件:在Java中,源代码通常被编写为.java文件
编译.java文件:使用Java编译器(javac命令)将.java文件编译成字节码文件(.class文件)
执行.class文件:使用Java虚拟机(java命令)执行.class文件,产生程序执行结果
程序执行结果:程序执行的结果通常是控制台输出或图形用户界面
注意事项
Java对大小写敏感
每个.java文件只能有一个public类,其他类不限
每一个类编译后,都是单独的.class
文件名需要跟public类名一致
不同的类可以有相同的方法名
Java 程序基础 转义字符
类型
转义字符
作用
制表符
\t
对齐文本
换行符
\n
换行
反斜杠
\\
显示反斜杠
单引号
\‘
显示单引号
双引号
\“
显示双引号
回车符
\r
回车,与换行相当
unicode编码
\uXXXX
编码对应的字符
标识符 合法标识符
1 2 3 4 5 6 username user_name a1 b2 $username _username
非法标识符
1 2 3 4 2sum your name #yourname int
常用关键字
abstract
continue
finally
interface
public
transient
boolean
default
float
long
return
true
break
do
for
native
short
try
byte
double
if
new
static
void
case
else
implements
null
synchronized
volatile
catch
extends
import
package
super
while
char
false
instanceof
private
this
const
class
final
int
protected
throw
goto
注释 单行注释
多行注释
方法注释
1 2 3 4 5 6 7 8 public int GetMax (int [] a)
String 转数值的常用方法 1 2 Integer.parseInt(); Float.parseFloat();
程序练习① 计算长方形的周长和面积 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Main { public static void main (String[] args) { float length, width; if (args.length == 0 ) { System.out.println("你没有输入参数!" ); return ; } length = Float.parseFloat(args[0 ]); width = Float.parseFloat(args[1 ]); float perimeter = 2f * (length + width); float area = length * width; System.out.println("周长:" + String.format("2 * (%f + %f) = %f" , length, width, perimeter)); System.out.println("面积:" + String.format("%f * %f = %f" , length, width, area)); } }
Text 1 2 周长:2 * (11.000000 + 45.000000) = 112.000000 面积:11.000000 * 45.000000 = 495.000000
计算整数平方(使用 System.in 输入数据) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.io.*;public class Main { public static void main (String[] args) { int data = 0 ,result; System.out.print("输入一个整数:" ); try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); data = Integer.parseInt(bufferedReader.readLine()); } catch (IOException e){ System.out.println("输入的类型不正确" ); e.printStackTrace(System.err); } result = data * data; System.out.printf("输入的内容:%d\n平方值:%d" , data, result); } }
Text 1 2 3 输入一个整数:1145 输入的内容:1145 平方值:1311025
Scanner 类输入数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.io.InputStream;import java.util.Scanner;public class Main { public static void main (String[] args) { InputStream inputStream = System.in; Scanner scanner = new Scanner(inputStream); System.out.print("请输入名称:" ); String name = scanner.next(); System.out.print("请输入价格:" ); int price = scanner.nextInt(); System.out.printf("名称:%s\n" , name); System.out.printf("价格:%d\n" , price); } }
Text 1 2 3 4 请输入名称:maimai 请输入价格:80000 名称:maimai 价格:80000
基本数据类型
数据类型
关键字
占用内存空间
取值范围(十进制)
字节型
byte
1B (8bit)
-128~127
短整型
short
2B (16bit)
-32768~32767
整型
int
4B (32bit)
-2147483648~2147483647
长整型
long
8B (64bit)
-9223372036854775808~9223372036854775807
单精度浮点型
float
4B (32bit)
-3.4E38~3.4E38
双精度浮点型
double
8B (64bit)
-1.7E308~1.7E308
布尔型
boolean
1B (8bit)
true/false
字符型
char
2B (16bit)
0~65535
八进制和十六进制 八进制以0
开头
十六进制以0x
开头
1 2 3 4 int a = 05 ; int b = 011 ; int c = 0xF ; int d = 0x11 ;
按位运算符
类型
符号
按位与(AND)
&
按位或(OR)
|
按位异或(XOR)
^
按位取反
~
位移运算符
符号
作用
>>
符号位不动,其余位右移,符号位后边正数补0,负数补1。又称带符号右移(除以2)
>>>
符号位一起右移,左边补0。又称无符号右移
<<
左移,右边补0。左移没有符号位(乘以2)
数据类型自动转换 不会出现问题的类型转换,编程语言可以做自动类型转换,比如低精度的数字向高精度的数字转换
自动类型转换可以发生在算数运算,也可以发生在赋值
数值精度顺序:double>float>long>int>short>byte
if-else 与 else if 语句 1 2 3 4 5 6 7 8 9 10 int a = 1145 ;int b = 1919 ;if (a > b) { System.out.println("a大于b" ); } else if (a < b) { System.out.println("a小于b" ); } else { System.out.println("a等于b" ); }
for,foreach 与 while 循环语句 break
跳出整个循环,continue
跳出当前循环,进行下一个循环
循环可嵌套
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 for (int i = 0 ; i < 10 ; i++) { System.out.println(i); } int [] a = {1 ,1 ,4 ,5 };for (int num: a) { System.out.println(num); } while (i < 10 ) { System.out.println(i); i++; }
switch 语句 if-else
两值比较的替代方案(可读性更好)
如果没有break
截断,程序会一直执行下去
1 2 3 4 5 6 7 8 9 10 switch (n) { case 1 : break ; case 2 : break ; default : }
变量的作用域 代码块里使用外层代码块的变量
代码块里创建变量
不能在外层代码块里使用内层代码块的变量。是否可以使用变量,也称作变量在某个代码块的可见性。也就是说,外层代码块创建的变量对内层代码块可见。内层代码块中创建的变量对外层代码块不可见
内层命名空间不可以重复定义外层代码块的变量,但是可以使用外层代码块的变量
代码块无论嵌套多少层,都遵守上述变量可见性的
作用域和命名空间 同一个命名空间中的变量不可以重名
为了避免变量名冲突,所以必须有命名空间
常量修饰符 标识符常量使用关键字 final 进行修饰,变量名采用大写字母
1 final double PI = 3.1425 ;
条件运算符 又称三目运算符,格式如下
表达式1 == true
时取表达式2
的结果,反之取表达式3
的结果
条件表达式可嵌套使用,例如
1 2 int y, x = -1 ;y = (x > 0 ) ? 5 : (x < 0 ) ? -8 : 0 ;
程序练习② 输出九九乘法表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Main { public static void main (String[] args) { for (int i = 1 ; i <= 9 ; i++) { String content = "" ; for (int j = 1 ; j <= 9 ; j++) { if (j > i) { break ; } content += String.format("%d*%d=%d\t" , i, j, i * j); } System.out.println(content); } } }
Text 1 2 3 4 5 6 7 8 9 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
猜数字游戏 其中用到了Math.random()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 import java.util.Scanner;public class RandomNumber { public static void main (String[] args) { Scanner scanner = new Scanner(System.in); int rangeStart = 1 ; int rangeEnd = 15 ; int guessTotal = 5 ; int totalGameCount = 0 ; int totalCorrectCount = 0 ; boolean stopGame = false ; System.out.println("输入负数结束游戏" ); while (!stopGame) { int guessLeft = guessTotal; int mod = rangeEnd - rangeStart; double randNum = Math.random(); int num = ((int ) (randNum * rangeEnd * 100 )) % mod; num += rangeStart; if (num <= rangeStart) { num = rangeStart + 1 ; } else if (num >= rangeEnd) { num = rangeEnd - 1 ; } System.out.printf("剩余机会:%d%n" , guessLeft); while (guessLeft > 0 ) { System.out.printf("请输入数字,范围(%d, %d):" , rangeStart, rangeEnd); int guess = scanner.nextInt(); if (guess < 0 ) { stopGame = true ; break ; } totalGameCount++; guessLeft--; if (guess > num) { System.out.println("输入的数字太大" ); } else if (guess < num) { System.out.println("输入的数字太小" ); } else { totalCorrectCount++; System.out.println("数字正确" ); break ; } } System.out.printf("进行了%d次游戏,其中猜对了%d次%n" , totalGameCount, totalCorrectCount); } } }
数组 数组是相同类型的变量的集合
每个元素都有一个固定的编号,称为索引(index),从0开始递增,类型为int
可以像造作变量一样读写数组中的任何一个元素
1 2 3 int [] intArray = new int [10 ];System.out.println(intArray[0 ]);
二维数组 二维数组是一维数组的自然延伸
1 double [][] scores = new double [3 ][6 ];
程序练习③ 随机生成成绩并查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import java.util.Scanner;public class QueryGrades { public static void main (String[] args) { String[] names = {"语文" , "数学" , "英语" , "物理" , "化学" , "生物" }; int namesCount = names.length; Scanner scanner = new Scanner(System.in); System.out.print("请输入要生成多少年的成绩:" ); int yearCount = scanner.nextInt(); double [][] scores = new double [yearCount][namesCount]; for (int i = 0 ; i < yearCount; i++) { for (int j = 0 ; j < namesCount; j++) { scores[i][j] = 80 + Math.random() * 20 ; } } while (true ) { System.out.print("要查询第几年的成绩(无效数字将结束查询):" ); int year = scanner.nextInt(); if (year <= 0 ){ break ; } System.out.print("要查看的课程编号:" ); int course = scanner.nextInt(); System.out.printf("第%d年的%s成绩是:%f%n" , year, names[course - 1 ], scores[year - 1 ][course - 1 ]); } } }
Java 面向对象 类(class)和对象 1 2 3 4 5 6 public class Student { String name; int age; int gender; }
操作对象的变量(点操作符) 1 2 3 4 5 6 7 8 Student stu1 = new Student(); stu1.name = "王小美" ; stu1.age = 20 ; stu1.gender = 1 ; System.out.println(stu1.name);
类和对象的关系 类是对象的模版,对象是类的一个实例
一个Java 程序中类名相同的类只能有一个,也就是类型不会重名
一个类可以有很多对象
一个对象只能根据一个类来创建
引用和类以及对象的关系 引用必须是、只能是一个类的引用
引用只能指向其所属的类型的类的对象
相同类型的引用之间可以赋值
只能通过指向一个对象的引用,来操作一个对象,比如访问某个成员变量
package 和 import 为了避免类在一起混乱,可以把类放在文件夹里。这时就需要用 package 语句告诉 Java 这个类在哪个 packace里。 package 语句要和源文件的目录完全对应,大小写要一致
package 读作包。一般来说,类都会在包里,而不会直接放在根目录
不同的包里可以有相同名字的类
一个类只能有一个 package 语句,如果有 package 语句,则必须是类的第一行有效代码
当使用另一个包里的类的时候,需要带上包名
每次使用都带包名很繁琐,可以在使用的类的上面使用 import 语句,一次性解决问题,就可以直接使用类了。就好像我们之前用过的 Scanner 类
import 语句可以有多个
如果需要 import 一个包中的很多类,可以使用*
通配符
1 import com.phone.parts.*;
类的全限定名 包名 + 类名 = 类的全限定名。也可以简称为类的全名
同一个 Java 程序中全限定名字不可重复
属性访问修饰符 被 public 修饰的属性,可以被任意包中的类访问
没有访问修饰符的属性,称作缺省的访问修饰符,可以被本包内的其他类和自己的对象
访问修饰符是一种限制或者允许属性访问的修饰符
程序练习④ 简易超市 Text 1 2 3 4 5 6 7 8 com └─bluesdawn ├─person │ └─Customer.java ├─supermarket │ ├─LittleSuperMarket.java │ └─Merchandise.java └─Run.java
1 2 3 4 5 6 7 package com.bluesdawn.person;public class Customer { public String name; public double money; public boolean isDrivingCar; }
1 2 3 4 5 6 7 8 9 10 package com.bluesdawn.supermarket;public class LittleSuperMarket { public String superMarketName; public String address; public int parkingCount; public double incomingSum; public Merchandise[] merchandises; public int [] merchandiseSold; }
1 2 3 4 5 6 7 8 9 package com.bluesdawn.supermarket;public class Merchandise { public String name; public String id; public int count; public double soldPrice; public double purchasePrice; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 package com.bluesdawn;import com.bluesdawn.person.Customer;import com.bluesdawn.supermarket.LittleSuperMarket;import com.bluesdawn.supermarket.Merchandise;import java.util.Scanner;public class Run { public static void main (String[] args) { LittleSuperMarket littleSuperMarket = new LittleSuperMarket(); littleSuperMarket.superMarketName = "SBGA超市" ; littleSuperMarket.address = "霓虹" ; littleSuperMarket.parkingCount = 100 ; littleSuperMarket.merchandises = new Merchandise[100 ]; littleSuperMarket.merchandiseSold = new int [littleSuperMarket.merchandises.length]; Merchandise[] all = littleSuperMarket.merchandises; for (int i = 0 ; i < all.length; i++) { Merchandise m = new Merchandise(); m.count = 514 ; m.id = "ID" + i; m.name = "乌蒙地插" + i; m.purchasePrice = Math.random() * 35000 ; m.soldPrice = (1 + Math.random()) * 40000 ; all[i] = m; } System.out.println("开始营业" ); boolean open = true ; Scanner scanner = new Scanner(System.in); while (open) { System.out.println("--------------------------" ); System.out.println("本店名称:" + littleSuperMarket.superMarketName); System.out.println("本店地址:" + littleSuperMarket.address); System.out.println("本店停车位:" + littleSuperMarket.parkingCount); System.out.println("本店营业额:" + littleSuperMarket.incomingSum); System.out.println("本店商品种类:" + littleSuperMarket.merchandises.length); System.out.println("--------------------------" ); Customer customer = new Customer(); customer.name = "编号" + (int ) (Math.random() * 10000 ); customer.money = (1 + Math.random()) * 50000 ; customer.isDrivingCar = Math.random() > 0.5 ; if (customer.isDrivingCar) { if (littleSuperMarket.parkingCount > 0 ) { System.out.println(customer.name + "顾客驾车,车位编号" + littleSuperMarket.parkingCount); littleSuperMarket.parkingCount--; } else { System.out.println("车位已满,欢迎下次光临" ); continue ; } } else { System.out.println("欢迎" + customer.name + "光临本店" ); } System.out.println("本店提供" + all.length + "种商品,欢迎选购" ); double totalCost = 0 ; while (true ) { System.out.print("请输入商品编号:" ); int index = scanner.nextInt(); if (index < 0 ) { break ; } if (index >= all.length) { System.out.println("商品编号不正确,请确保编号在" + (all.length - 1 ) + "(含)之内" ); } Merchandise m = all[index]; System.out.println("要选购的是" + m.name + "\n单价是" + m.soldPrice); System.out.print("要购买多少台:" ); int numToBuy = scanner.nextInt(); if (numToBuy <= 0 ) { System.out.println("顾客取消购买" ); } if (numToBuy > m.count) { System.out.println("此商品没有那么多的库存" ); } if (numToBuy * m.soldPrice > customer.money) { System.out.println("顾客所带的钱不够,剩余" + customer.money); continue ; } totalCost += numToBuy * m.soldPrice; m.count -= numToBuy; littleSuperMarket.merchandiseSold[index] += numToBuy; customer.money -= totalCost; } if (customer.isDrivingCar) { littleSuperMarket.parkingCount++; } System.out.println("顾客" + customer.name + "共消费了" + totalCost); littleSuperMarket.incomingSum = totalCost; System.out.print("还继续营业吗(Y/N):" ); String status = scanner.next(); if (status.matches("^([Nn][Oo]|[Nn])$" )) { open = false ; } } System.out.println("结束营业" ); System.out.println("--------------------------" ); System.out.println("今天的营业额为" + littleSuperMarket.incomingSum); System.out.println("营业情况如下:" ); for (int i = 0 ; i < littleSuperMarket.merchandiseSold.length; i++) { Merchandise m = all[i]; int numSold = littleSuperMarket.merchandiseSold[i]; if (numSold > 0 ) { double incoming = m.soldPrice * numSold; double netIncoming = (m.soldPrice - m.purchasePrice) * numSold; System.out.printf("售出了%d台%n销售额为%f%n净利润为%f%n" , numSold, incoming, netIncoming); } } System.out.println("--------------------------" ); } }
类的行为(方法) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.bluesdawn.supermarket;public class Merchandise { public String name; public String id; public int count; public double soldPrice; public double purchasePrice; } public void describe () { System.out.println("内容" ); }
方法的返回值类型 返回值类型可以是自定义的类名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public void print () { System.out.println("Hello world!" ); } public int getInt () { return 2 ; } public double getDouble () { return 1.414 ; } public boolean getBoolean () { return true ; }
方法传递参数 1 2 3 public int add (int a, int b) { return a + b; }
参数和返回值是怎么传递的 参数和方法里的局部变量可以认为是一样的东西。只是在方法调用之前,会用实参给参数的形参赋值
发生在代码块里的,就让它留在代码块里。方法执行完毕,参数和方法的局部变量的数据就会被删除回收。就好像演草纸,作用是计算一个值,算好之后,演草纸就可以扔了
调用一个有返回值的方法时,就好像访问一个成员变量
1 2 3 4 5 6 7 8 double totalCost = m.buy((c + 2 ) * 5 );System.out.println("商品总价为:" + totalCost); boolean biggerThan = m.totalValueBiggerThan(littleSuperMarket.merchandises[index + 1 ]);System.out.println(biggerThan);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int paramPrime = 7 ;Merchandise paramRef = littleSuperMarket.merchandises[2 ]; m.willOutsideValueChangeIfParameterVallueChangeHerePrime(paramPrime); m.willOutsideValueChangeIfParameterVallueChangeHereRef(paramRef); System.out.println(paramPrime); System.out.println(paramRef);
this 自引用 方法里隐藏着一个this自引用,指向调用这个方法的对象。
使用一个对象调用方法,也叫做在这个对象上调用方法。因为方法可以访问这个对象的值
访问一个成员变量的完整形态,是“this.成员变量的名字”
1 2 3 4 public void addCount (int count) { this .count += count; System.out.println("该方法使用的对象是:" + this ); }
Java 进阶 把操作成员的变量的代码都放在类里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.bluesdawn.supermarket;public class Merchandise { public String name; public String id; public int count; public double soldPrice; public double purchasePrice; public void init (String name, String id, int count, double soldPrice, double purchasePrice) { this .name = name; this .id = id; this .count = count; this .soldPrice = soldPrice; this .purchasePrice = purchasePrice; } public void describe () { System.out.printf("名称:%s%n编号:%s%n库存:%d%n单价:%f%n进价:%f%n毛利润:%f%n" , name, id, count, soldPrice, purchasePrice, soldPrice - purchasePrice); } }
1 2 3 4 5 6 7 8 9 10 11 12 package com.bluesdawn;import com.bluesdawn.supermarket.Merchandise;public class Run { public static void main (String[] args) { Merchandise merchandise = new Merchandise(); merchandise.init("书桌" , "DESK1145" , 40 , 99 , 59 ); merchandise.describe(); } }
方法的签名和重载 方法签名:方法名+依次参数类型。注意,返回值不属于方法签名。方法签名是一个方法在一个类中的唯一标识
同一个类中方法可以重名,但是签名不可以重复。一个类中如果定义了名字相同,签名不同的方法,就叫做方法的重载
看代码:重写我们的购买方法,理解方法签名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public double buy () { return buy(1 ); } public double buy (int count) { return buy(count, false ); } public double buy (int count, boolean isVip) { if (this .count < count) { return -1 ; } this .count -= count; double totalCost = count * soldPrice; if (isVip) { return totalCost * 0.95 ; } else { return totalCost; } }
重载参数的匹配规则 依次使用 byte,short,int,long,float,double 类型的参数调用buy方法,哪个方法会被调用呢?
无论是否重载参数类型可以不完全匹配的规则是“实参数可以自动类型转换成形参类型”
重载的特殊之处是,参数满足自动自动类型转换的方法有好几个,重载的规则是选择最“近”的去调用
构造实例的方法 构造方法 (constructor) 的方法名必须与类名一样,而且构造方法没有返回值
构造方法也可以重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.bluesdawn.supermarket;public class Merchandise { public String name; public String id; public int count; public double soldPrice; public double purchasePrice; public Merchandise (String name, String id, int count, double soldPrice, double purchasePrice) { this .name = name; this .id = id; this .count = count; this .soldPrice = soldPrice; this .purchasePrice = purchasePrice; } public void describe () { System.out.printf("名称:%s%n编号:%s%n库存:%d%n单价:%f%n进价:%f%n毛利润:%f%n" , name, id, count, soldPrice, purchasePrice, soldPrice - purchasePrice); } }
1 2 3 4 5 6 7 8 9 10 11 package com.bluesdawn;import com.bluesdawn.supermarket.Merchandise;public class Run { public static void main (String[] args) { Merchandise merchandise = new Merchandise("书桌" , "DESK1145" , 40 , 99 , 59 ); merchandise.describe(); } }
静态变量 静态变量使用 static 修饰符
静态变量如果不赋值,Java也会给它赋以其类型的初始值
静态变量一般使用全大写字母加下划线分割。这是一个习惯用法
所有的代码都可以使用静态变量,只要根据防范控制符的规范,这个静态变量对其可见即可
比如 public 的静态变量,所有的代码都可以使用它
1 public static double DISCOUNT_FOR_VIP = 0.95 ;
1 2 import static com.bluesdawn.supermarket.Merchandise.*;
静态变量一旦变化,所有使用这个静态变量的地方的值都会变
静态方法 静态方法可以访问静态变量,包括自己类的静态变量和在访问控制符允许的别的类的静态变量
静态方法不属于某个实例,隐藏没有this自引用
1 2 3 public static double getVIPDiscount () { return DISCOUNT_FOR_VIP; }
静态代码块 1 2 3 4 5 6 7 static { BASE_DISCOUNT = 0.99 ; VIP_DISCOUNT = 0.85 ; SVIP_DISCOUNT = 0.75 ; System.out.println("静态代码块里的SVIP_DISCOUNT" + SVIP_DISCOUNT); }
String 的常用方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 String.length(); String.toUpperCase(); String.toLowerCase(); String.charAt(1 ); String.substring(5 ); String.substring(1 , 5 ); String.split("_" ); String.indexOf("_" ); String.lastIndexOf("_" ); String.contains("apple" ); String.equals(anotherString); String.equalsIgnoreCase(anotherString); String.trim();
程序练习⑤ 简易实现ai智障对话 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package com.bluesdawn.talk;public class Talk { public String answer (String question) { String ret; ret = handleCanStart(question); if (ret != null ) { return ret; } ret = handleAskTail(question); if (ret != null ) { return ret; } return handleUnknown(question); } public String handleCanStart (String question) { String[] canStart = new String[]{"会" , "能" , "有" , "敢" , "在" }; for (String s : canStart) { if (question.startsWith(s)) { return s + "!" ; } } return null ; } public String handleAskTail (String question) { String[] askTail = new String[]{"吗?" , "吗?" , "吗" }; for (String s : askTail) { if (question.endsWith(s)) { return question.replace(s, "!" ); } } return null ; } public String handleUnknown (String question) { return question + "!" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.bluesdawn.talk;import java.util.Scanner;public class Main { public static void main (String[] args) { Talk talk = new Talk(); Scanner in = new Scanner(System.in); while (true ) { String input = in.next(); if ("exit" .equals(input)) { System.out.println("再见" ); break ; } String answer = talk.answer(input); System.out.println(answer); } } }
System 扩展 1 System.currentTimeMillis();
StringBuilder 1 2 3 4 5 6 7 8 9 StringBuilder stringBuilder = new StringBuilder("此内容可空" ); stringBuilder.append("某些内容" ).append("114514" ); stringBuilder.toString(); stringBuilder.reverse.toString(); stringBuilder.delete(0 , 4 ).toString(); stringBuilder.insert(3 , "LLLLL" ).toString();
1 2 3 4 5 @Override public StringBuilder append (String str) { super .append(str); return this ; }
类的继承 1 2 3 4 5 6 public class 子类名 extends 要继承的父类 { public double buy (int count) { System.out.println("购买成功" ); return super .buy(count); } }
父类与子类的引用赋值关系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 Phone ph = new Phone( "手机001" , "Phone001" , 100 , 1999 , 999 , 4.5 , 3.5 , 4 , 128 , "索尼" , "安卓" ); MerchandiseV2 m = ph; MerchandiseV2 m2 = new Phone( "手机002" , "Phone002" , 100 , 1999 , 999 , 4.5 , 3.5 , 4 , 128 , "索尼" , "安卓" ); ph.getBrand(); Phone aPhone = (Phone) m2; ShellColorChangePhone shellColorChangePhone = new ShellColorChangePhone( "手机002" , "Phone002" , 100 , 1999 , 999 , 4.5 , 3.5 , 4 , 128 , "索尼" , "安卓" ); MerchandiseV2 ccm = shellColorChangePhone; Phone ccp = (Phone) ccm; ShellColorChangePhone scp = (ShellColorChangePhone) ccm; ShellColorChangePhone notCCP = (ShellColorChangePhone) m2;
instanceOf 操作符 1 2 3 4 5 6 if (m instanceof Phone) { Phone phone = (Phone)m; System.out.println(phone.getBrand()); }
final 修饰符 修饰class时,该类无法被继承
修饰变量时,该变量无法被外部修改
修饰方法时,该方法不能被子类方法覆盖
修饰数组时,该数组内的元素可以被赋值,但不能直接指向另一个数组
可变参数 1 public static void main (String... args)
反射 1 import java.lang.reflect.Field;
1 2 3 4 5 6 7 8 9 10 11 12 13 Class clazz = m100.getClass(); clazz.getName(); clazz.getSimpleName(); Field countField = clazz.getField("count" ); countField.getType(); countField.get(m100); Method buyMethod = clazz.getMethod("buy" , int .class); Method equalsMethod = clazz.getMethod("equals" , Object.class); buyMethod.invoke(m100, 10 );
enum 枚举 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public enum MusicGame { ARCAEA("616" ), PHIGROS("鸽游" ), MAIMAI("SBGA" ); private String company; MusicGame(String company) { this .company = company; } public String GetCompany () { return company; } @Override public String toString () { return "MusicGame{" + "company='" + company + '\'' + '}' ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Run { public static void main (String[] args) { for (MusicGame musicGame : MusicGame.values()) { System.out.println("-------------------------" ); System.out.println(musicGame.GetCompany()); System.out.println(musicGame.ordinal()); System.out.println(musicGame.name()); System.out.println("-------------------------" ); } System.out.println(MusicGame.valueOf("MAIMAI" )); Scanner scanner = new Scanner(System.in); System.out.print("请输入音游名称:" ); String musicGameName = scanner.next(); MusicGame musicGame = MusicGame.valueOf(musicGameName.trim().toUpperCase()); System.out.println(musicGame); } }
接口 基本实现方式
1 2 3 4 public interface Glass { void Test1 () ; int GetCount () ; }
1 2 3 4 public interface Ceramics { void Test2 () ; int Test3 () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Phone extends Merchandise implements Glass , Ceramics { private int count; public void Test1 () { } public int GetCount () { return count; } public void Test2 () { } public void Test3 () { } }
1 2 3 4 5 6 Phone phone = new Phone(); Glass glass = phone; Ceramics ceramics = phone; Merchandise merchandise = phone;
接口可以有缺省和私有方法,带方法体
1 2 3 4 5 6 7 8 public interface Ceramics { default int add (int a, int b) { return a + b; } private String hello () { return "真假陶瓷" ; } }
Collection 集合 简易链表实现(不完全)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 import java.util.*;public class MyLinkedList implements List { static class ListNode { ListNode prev; ListNode next; Object value; public ListNode (ListNode prev, ListNode next, Object value) { this .prev = prev; this .next = next; this .value = value; } } private ListNode start = null ; private ListNode tail = null ; private int size = 0 ; @Override public int size () { return size; } @Override public boolean isEmpty () { return size == 0 ; } @Override public boolean contains (Object o) { ListNode curr = start; while (curr != null ) { if (Objects.equals(curr.value, o)) { return true ; } curr = curr.next; } return false ; } @Override public boolean add (Object o) { ListNode newNode = new ListNode(tail, null , o); if (start==null ){ start=newNode; } if (tail!=null ){ tail.next=newNode; } tail = newNode; size++; return true ; } @Override public void clear () { start = null ; tail = null ; size = 0 ; } @Override public Object get (int index) { if (index > size || index < 0 ) { throw new IndexOutOfBoundsException(); } ListNode curr = start; for (int i = 0 ; i < index; i++) { curr = curr.next; } return curr.value; } }
1 2 3 new ArrayList();new LinkedList();new HashSet();
Generics 泛型 ArrayList
1 2 3 4 List<int > newList = new ArrayList<>(); for (int i = 0 ; i < 5 ; i++) { newList.add(i); }
泛型自定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class MyGenericClass <First , Second > { private First first; private Second second; public MyGenericClass (First first, Second second) { this .first = first; this .second = second; } public First getFirst () { return first; } public void setFirst (First first) { this .first = first; } public Second getSecond () { return second; } public void setSecond (Second second) { this .second = second; } public <Another> Another getAnother (Object val) { return (Another) val; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class DefineGenericTypesAppMain { public static void main (String[] args) throws NoSuchFieldException { Field field2 = MyGenericClass.class.getDeclaredField("first" ); System.out.println("first的类型是" + field2.getType()); MyGenericClass<String, Object> test = new MyGenericClass<>("inst1" , new Object()); MyGenericClass<String, Object> test2 = new MyGenericClass<>("inst2" , "aaabbb" ); String first = test.getFirst(); System.out.println(first); String another = test.getAnother("safe" ); MyGenericClass mc = new MyGenericClass("" , "" ); MyGenericClass<GrandParent, Parent> cast = mc; cast.getFirst(); } }