java 快速入门 + 简介 (回忆篇)
Java快速入门(简介)
java特点
简单
相对于C++,没有指针,自动分配和回收内存空间
面向对象
动态绑定,支持类之间单继承,支持接口之间多继承,支持类和接口之间实现机制
分布式
有网络应用编程接口,提供用于网络应用编程的类库
健壮
强类型机制、异常处理、垃圾的自动收集,指针的丢弃,安全检查机制
安全
Java 语言具有的许多安全特性以外,Java 对通过网络下载的类具有一个安全防范机制,提供安全管理机制
体系结构中立
编译为class字节码文件,可以实现任何系统运行
可移植
严格规定了各个基本数据类型的长度,Java 编译器是用 Java 实现的,Java 的运行环境是用 ANSI C 实现
解释性
Java 平台中的 Java 解释器对字节码进行解释执行
高性能
运行速度比 python 快
多线程
java中线程是一种特殊的对象,Java 语言支持多个线程的同时执行,并提供多线程之间的同步机制
动态
类能够动态地被载入到运行环境,也可以通过网络来载入所需要的类
基础语法
对象
类的实例,有状态和行为
类
是一个模板,描述一类对象行为和状态
方法
方法就是行为,一个类可以有很多方法
实例变量
每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定
java程序
public static void main(String[] args)
// 访问修饰符 关键字 返回类型 方法名 String类 字符串数组
基本语法
大小写敏感
类名
类名的首字母应该大写,后面每个单词首字母大写
方法名
方法名首字母小写,后面每个单词首字母大写
源文件名
源文件名必须和类名相同
主方法入口
public static void main(String[] args)
标识符
- 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始
- 首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合
- 关键字不能用作标识符
- 标识符是大小写敏感的
- 合法标识符举例:age、$salary、_value、__1_value
- 非法标识符举例:123abc、-salary
修饰符
修饰类中方法和属性
访问控制修饰符
default, public, protected, private
非访问控制修饰符
final, abstract, static, synchronized
变量
- 局部变量
- 类变量(静态变量)
- 成员变量(非静态变量)
数组
数组是储存在堆上的对象,可以保存多个同类型变量
枚举
枚举限制变量只能是预先设定好的值,使用枚举可以减少代码中的 bug,枚举可以单独声明或者声明在类里面。方法、变量、构造函数也可以在枚举中定义
public class Main {
public static void main(String[] args) {
Juice juice = new Juice();
System.out.println(juice.size = Juice.JuiceSize.Sma);
}
}
class Juice{
enum JuiceSize{Sma,Med,Lag}
JuiceSize size;
}
java关键字
访问控制
private 私有的
protected 受保护的
public 公共的
default 默认
类,方法和变量修饰符
abstract 声明抽象
class 类
extends 继承
final 不可变的
implements 实现接口
interface 接口
native 本地原生方法
new 创建
static 静态
synchronized 线程同步
程序控制语句
break 跳出循环
case 定义一个值供switch选择
continue 继续
default 默认
do 运行
else 否则
for 循环
if 如果
instanceof 实例
return 返回
switch 根据值选择执行
while 循环
错误处理
catch 捕获异常
finally 有没有异常都会执行
throw 抛出异常
throws 声明一个异常可能被抛出
try 捕获异常
包相关
import 引入
package 包
基本类型
boolean 布尔型
byte 字节型
char 字符型
double 双精度浮点型
float 单精度浮点型
int 整型
long 长整型
short 短整型
变量引用
super 父类
this 本类
void 无返回值
注释
//
/* */
/**
*/
继承
一个类可以由其他类派生,如果你要创建一个类,而且已经存在一个类具有你所需要的属性或方法,那么你可以将新创建的类继承该类。
被继承的类称为超类,派生类称为子类
接口
接口只定义派生要用到的方法,但是方法的具体实现完全取决于派生类
java程序基础
变量
在Java中,变量分为两种:基本类型的变量和引用类型的变量
基本类型包括整型,浮点型,布尔型,字符型。
public class Main {
public static void main(String[] args) {
int age = 7;
// primary student的定义: 6~12岁
boolean isPrimaryStudent = age>8;
System.out.println(isPrimaryStudent ? "Yes" : "No");
}
}
与运算和或运算是短路运算;
三元运算b ? x : y
后面的类型必须相同,三元运算也是“短路运算”,只计算x
或y
。
数组
数组一旦创建后,大小就不可变
public class Main {
public static void main(String[] args) {
String[] names = {"ABC", "XYZ", "zoo"};
String s = names[1];
names[1] = "cat";
System.out.println(s); // s是"XYZ"还是"cat"?
}
}
原来names[1]
指向的字符串"XYZ"
并没有改变,仅仅是将names[1]
的引用从指向"XYZ"
改成了指向"cat"
,其结果是字符串"XYZ"
再也无法通过names[1]
访问到了
java流程控制
break 和 continue
break
语句可以跳出当前循环;
break
语句通常配合if
,在满足条件时提前结束整个循环;
break
语句总是跳出最近的一层循环;
continue
语句可以提前结束本次循环;
continue
语句通常配合if
,在满足条件时提前结束本次循环。
数组操作
多维数组
多维数组遍历
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[][] ns = {
{ 1, 2, 3, 4 },
{ 5, 6 },
{ 7, 8, 9 }
};
System.out.println(Arrays.deepToString(ns));
}
}
// [[1, 2, 3, 4], [5, 6], [7, 8, 9]]
命令行参数
Java程序的入口是main
方法,而main
方法可以接受一个命令行参数,它是一个String[]
数组
public class Main {
public static void main(String[] args) {
for (String arg : args) {
if ("-version".equals(arg)) {
System.out.println("v 1.0");
break;
}
}
}
}
// 切换到命令行
javac Main.java
java Main -version
特殊类
Number & Math类
实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型
Java 语言为每一个内置数据类型提供了对应的包装类。
包装类 | 基本数据类型 |
---|---|
Boolean | boolean |
Byte | byte |
Short | short |
Integer | int |
Long | long |
Character | char |
Float | float |
Double | double |
这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。相似的,编译器也可以把一个对象拆箱为内置类型。
public class Main {
public static void main(String[] args) {
Integer i = 8;
float v = i.floatValue();
System.out.println(i.compareTo(4)); // 大于4,返回1
System.out.println(i.compareTo(666)); // 小于666,返回-1
}
}
Character类
Character a = new Character('a');
Character a1 = 'a'; //自动装箱
//char -> Character 装箱
//Character -> char 拆箱
String 类
连接String
public class Main {
public static void main(String[] args) {
String s1 = "i like";
String s2 = " i";
System.out.println(s1.concat(s2));
}
}
格式化字符串
public static void main(String[] args) {
System.out.printf("%d",2333);
System.out.println();
System.out.printf("%s","hello world");
}
StringBuffer类
public static void main(String[] args) {
StringBuffer sb = new StringBuffer(100);
sb.append("虽然我和他");
System.out.println(sb);
sb.append("hiohiouhniol");
sb.insert(5,"已十年不见,但我知道我会永远怀念他。");
System.out.println(sb);
sb.delete(23,99);
System.out.println(sb);
}
Arrays类
public static void main(String[] args) {
int[] arr= {123,45,3,2,13,2};
System.out.println(Arrays.toString(arr));
int i = Arrays.binarySearch(arr, 3); // 二分查找
System.out.println("对应下标:" + i);
Arrays.fill(arr,2,6,4); // 赋值
System.out.println(Arrays.toString(arr));
Arrays.sort(arr); // 快速排序
System.out.println(Arrays.toString(arr));
}
日期时间
Date类
格式化输出时间
public static void main(String[] args) throws Exception{
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(simpleDateFormat.format(date));
}
public static void main(String[] args) {
// 初始化 Date 对象
Date date = new Date();
//c的使用
System.out.printf("全部日期和时间信息:%tc%n",date);
//f的使用
System.out.printf("年-月-日格式:%tF%n",date);
//d的使用
System.out.printf("月/日/年格式:%tD%n",date);
//r的使用
System.out.printf("HH:MM:SS PM格式(12时制):%tr%n",date);
//t的使用
System.out.printf("HH:MM:SS格式(24时制):%tT%n",date);
//R的使用
System.out.printf("HH:MM格式(24时制):%tR",date);
}
求时间间隔
public static void main(String[] args) throws Exception{
long t1 = System.currentTimeMillis();
Thread.sleep(2000);
long t2 = System.currentTimeMillis();
long t = t2 - t1;
System.out.println(t);
}
Calendar类
public static void main(String[] args) throws Exception{
Calendar c = Calendar.getInstance();
int i = c.get(Calendar.YEAR);
int month = Calendar.MONTH;
int i1 = c.get(month);
int i2 = c.get(Calendar.DATE);
int i3 = c.get(Calendar.HOUR_OF_DAY);
int i4 = c.get(Calendar.MINUTE);
System.out.println(c.get(Calendar.SECOND));
System.out.println(Calendar.DAY_OF_WEEK);
}
正则表达式
正则表达式是用字符串描述的一个匹配规则,使用正则表达式可以快速判断给定的字符串是否符合匹配规则
// 匹配国内的电话号码规则:3~4位区号加7~8位电话,中间用-连接
public static void main(String[] args){
String re = "\\d{2,3}-\\d{6,7}";
System.out.println("010-12345678".matches(re)); // t
System.out.println("020-9999999".matches(re)); // t
System.out.println("0755-7654321".matches(re)); // t
System.out.println("010 12345678".matches(re)); // f
System.out.println("A20-9999999".matches(re)); // f
System.out.println("0755-7654.321".matches(re));// f
}
匹配规则:
. -> 任意字符
\d -> 数字0~9 \D -> 非数字
\w -> 大小写字母,数字,下划线 \W -> 取反
\s -> 空格,Tab键 \S -> 取反
A+ -> 至少一个字符
A? -> 0个 1个
A{3} -> 3个
A{2,3} -> 2~3个
A{2,} -> 至少2个
复杂匹配规则
// 7~8位数字的电话号码不能以0开头
[1-9]\\d{6,7}
// 排除法
[^1-9]\\d{6,7}
或匹配
public static void main(String[] args){
String re = "java|C";
System.out.println("java".matches(re));
System.out.println("C".matches(re));
System.out.println("jvav".matches(re));
}
// 前面有条件时加括号即可
public static void main(String[] args){
String re = "learn\\s(java|php|go)";
System.out.println("learn java".matches(re));
System.out.println("learn Java".matches(re));
System.out.println("learn php".matches(re));
System.out.println("learn Go".matches(re));
}
分组匹配
public static void main(String[] args){
Pattern p = Pattern.compile("(\\d{3,4})-(\\d{7,8})");
Matcher m = p.matcher("010-12345678");
if (m.matches()) {
String g1 = m.group(1);
String g2 = m.group(2);
System.out.println(g1);
System.out.println(g2);
}else {
System.out.println("匹配失败");
}
}
非贪婪匹配
正则表达式默认贪婪匹配
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(\\d+)(0*)");
Matcher matcher = pattern.matcher("1230000");
if (matcher.matches()) {
System.out.println("group1=" + matcher.group(1)); // "1230000"
System.out.println("group2=" + matcher.group(2)); // ""
}
}
0 匹配到了前面一组,这就是贪婪的结果
在规则\d+
后面加个?
即可表示非贪婪匹配
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(\\d+?)(0*)");
Matcher matcher = pattern.matcher("1230000");
if (matcher.matches()) {
System.out.println("group1=" + matcher.group(1)); // "123"
System.out.println("group2=" + matcher.group(2)); // "0000"
}
}
正则表达式匹配默认使用贪婪匹配,可以使用?
表示对某一规则进行非贪婪匹配
搜索和替换
分割字符串
public static void main(String[] args) {
System.out.println(Arrays.toString("a b c".split("\\s")));
System.out.println(Arrays.toString("a b c".split("\\s")));
System.out.println(Arrays.toString("a, b ;; c".split("[\\,\\;\\s]+")));
// [a, b, c]
// [a, b, , c]
// [a, b, c]
}
替换字符串
public static void main(String[] args) {
String s = "The quick\t\t brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s+", " ");
System.out.println(r); // "The quick brown fox jumps over the lazy dog."
}
反向引用
如果我们要把搜索到的指定字符串按规则替换,比如前后各加一个<b>xxxx</b>
,这个时候,使用replaceAll()
的时候,我们传入的第二个参数可以使用$1
、$2
来反向引用匹配到的子串。
public class Main {
public static void main(String[] args) {
String s = "the quick brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s([a-z]{4})\\s", " <b>$1</b> ");
System.out.println(r);
}
}
// the quick brown fox jumps <b>over</b> the <b>lazy</b> dog.
java方法
方法格式
可变参数
public static void main(String[] args) {
// 调用可变参数的方法
printMax(34, 3, 3, 2, 56.5);
printMax(new double[]{1, 2, 3});
}
public static void printMax( double... numbers) {
if (numbers.length == 0) {
System.out.println("No argument passed");
return;
}
double result = numbers[0];
for (int i = 1; i < numbers.length; i++){
if (numbers[i] > result) {
result = numbers[i];
}
}
System.out.println("The max value is " + result);
}
finalize方法
在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象
public class FinalizationDemo {
public static void main(String[] args) {
Cake c1 = new Cake(1);
Cake c2 = new Cake(2);
Cake c3 = new Cake(3);
c2 = c3 = null;
System.gc(); //调用Java垃圾收集器
}
}
class Cake extends Object {
private int id;
public Cake(int id) {
this.id = id;
System.out.println("Cake Object " + id + "is created");
}
protected void finalize() throws java.lang.Throwable {
super.finalize();
System.out.println("Cake Object " + id + "is disposed");
}
}
流、文件和IO
Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
// 用 read() 方法从控制台不断读取字符直到用户输入 q
public static void main(String[] args) throws Exception{
char c;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("输入字符,按 q 退出");
do {
c = (char) br.read();
System.out.println(c);
}while (c != 'q');
}
读取一个字符串需要使用 BufferedReader 的 readLine() 方法
下面的程序读取和显示字符行直到你输入了单词"end"
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter lines of text.");
System.out.println("Enter 'end' to quit.");
do {
str = br.readLine();
System.out.println(str);
}while (! str.equals("end"));
}
输入流和输出流的类层次图
FileInputStream
用于从文件读取数据,对象可以用关键字new创建
InputStream f = new FileInputStream("D:/");// 用字符串类型文件名创建一个输入流对象来读取文件
FileOutputStream
用于创建一个文件并向文件中写数据
OutputStream f = new FileOutputStream("D:/"); // 用字符串类型文件名创建一个输出流对象来读取文件
目录
创建目录
public static void main(String[] args) throws IOException {
String dirname = "/tmp/user/java/bin";
File d = new File(dirname);
d.mkdir(); // 创建
d.isDirectory(); // 确认
d.delete(); // 删除
}
Scanner类
使用 next / nextLine 方法
通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("next方法接收:");
if (scanner.hasNext()){ // hasNextLine
String str = scanner.next(); // nextLine
System.out.println("输入的数据为:" + str);
}
scanner.close();
}
java 异常处理
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。
运行时异常: 运行时异常是可能被程序员避免的异常。
错误: 错误不是异常,而是脱离程序员控制的问题。
Exception 类的层次
处理异常
捕获异常
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
多重捕获块
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
// 可以在 try 语句后面添加任意数量的 catch 块。
抛出异常
方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开
import java.io.*;
public class className
{
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
// Method implementation
}
//Remainder of class definition
}
finally关键字
finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
try-with-resources
JDK7后新增的语法糖 try-with-resource 打开资源,可以在语句执行完毕确保每个资源自动关闭
try (resource declaration) {
// 使用的资源
} catch (ExceptionType e1) {
// 异常块
}
import java.io.*;
public class RunoobTest {
public static void main(String[] args) {
String line;
try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
while ((line = br.readLine()) != null) {
System.out.println("Line =>"+line);
}
} catch (IOException e) {
System.out.println("IOException in try block =>" + e.getMessage());
}
}
}
// IOException in try block =>test.txt (系统找不到指定的文件。)
try-with-resources 处理多个资源
import java.io.*;
import java.util.*;
class RunoobTest {
public static void main(String[] args) throws IOException{
try (Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
while (scanner.hasNext()) {
writer.print(scanner.nextLine());
}
}
}
}
声明自定义异常
class MyException extends Exception{
}
通用异常
java中定义了两种类型的异常和错误
-
JVM(Java虚拟机) 异常:由 JVM 抛出的异常或错误。
-
程序级异常:由程序或者API程序抛出的异常。例如 IllegalArgumentException 类,IllegalStateException 类。
添加一些注意点:
所有的Java语句必须以;
结尾!
无论是()
、[]
还是{}
,所有的括号必须一一匹配!
主方法的代码只能写在{}
中!
变量和C语言中的变量不同,Java中的变量是存放在JVM管理的内存中,C语言的变量存放在内存(某些情况下需要手动释放内存,而Java会自动帮助我们清理变量占据的内存)Java和C++很类似,但是没有指针!Java也叫C++--
注意:标识符不能为以下内容:
- 标识符以由大小写字母、数字、下划线(_)和美元符号($)组成,但是不能以数字开头。
- 大小写敏感!
- 不能有空格、@、#、+、-、/ 等符号
- 应该使用有意义的名称,达到见名知意的目的,最好以小写字母开头
- 不可以是 true 和 false
- 不能与Java语言的关键字重名
新的内容:
计算机二进制表示
一个位是1bit 一个字节是8bit
一个字是16bit 双字 32bit 四字 64bit
我们一般用字节描述数据大小
4个bit位,表示数字范围: 0000(0) ~ 1111(15)
java中首位是符号位:1111(-7) ~ 0111(+7)
现在,4bit表示 -7 ~ +7 ,这种表示方法叫 原码
计算机加减法
原码
无法进行加减
反码
负数反码是原码,符号不变,其他取反
补码
反码 + 1
用补码实现加减法即可
小数类型
float 单精度浮点型 32bit 4字节
double 双精度浮点型 64bit 8字节
二进制浮点数 V 可以表示成下面的形式:
V = (-1)^S × M × 2^E
类型转换
隐式类型转换
隐式类型转换支持字节数小的类型自动转换为字节数大的类型,整数类型自动转换为小数类型
显示类型转换
显示类型转换也叫做强制类型转换,也就是说,违反隐式转换的规则,牺牲精度强行进行类型转换
数据类型自动提升
在参与运算时(也可以位于表达式中时,自增自减除外),所有的byte型、short型和char的值将被提升到int型
逻辑运算
&& //与运算,要求两边同时为true才能返回true
|| //或运算,要求两边至少要有一个为true才能返回true
! //非运算,一般放在表达式最前面,表达式用括号扩起来,表示对表达式的结果进行反转
位运算
& //按位与,注意,返回的是运算后的同类型值,不是boolean!
| //按位或
^ //按位异或 0 ^ 0 = 0
~ //按位非
三目运算
为了简化代码而生
int a = 7, b = 15;
String str = a > b ? "行" : "不行"; // 判断条件(只能是boolean,或返回boolean的表达式) ? 满足的返回值 : 不满足的返回值
System.out.println("汉堡做的行不行?"+str); //汉堡做的行不行?不行
面向过程编程实战
打印九九乘法表
public static void main(String[] args) {
for (int i = 1; i < 10; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(" " + i + "×" + j + "=" + (i*j));
}
System.out.println();
}
}
// 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
求1000以内的水仙花数
打印1000以内所有满足水仙花的数,“水仙花数”是指一个三位数其各位数字的立方和等于该数本身
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
if(((i - (i%10) - (i%100 - i%10))/100) == 0)continue;
if ((i%10)*(i%10)*(i%10) + ((i%100 - i%10)/10)*((i%100 - i%10)/10)*((i%100 - i%10)/10) + ((i - (i%10) -
(i%100 - i%10))/100)*((i - (i%10) - (i%100 - i%10))/100)*((i - (i%10) - (i%100 - i%10))/100) == i){
System.out.println(i);
}
}
}
青蛙跳台阶问题
困难:一共有n个台阶,一只青蛙每次只能跳一阶或是两阶,那么一共有多少种跳到顶端的方案?例如n=2,那么一共有两种方案,一次性跳两阶或是每次跳一阶。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println(frog(n));
}
public static int frog(int n){
if (n == 1) return 1;
if (n == 2) return 2;
return frog(n-1)+frog(n-2);
}