Java基础
了解Java
起源发展
-
Java 诞生1995年,Sun公司
-
Oracle于2009年从Sun收购,变为Oracle-java
-
最新为jdk8 / jdk1.8 / Java8
Java版本
- JavaSE(基础、标准版)基础学习 --- 基础开发、部署桌面
- JavaEE(企业版)开发方向 --- 商务网站、ERP
- JavaME(微型版)了解即可 --- 可视电话、数字机顶盒
Java特性
-
跨平台性,底层由C++开发,源代码开源(C是C++的子集)
-
简单性,相对其他语言,Java不支持多继承,屏蔽指针,相对简单
-
面向对象(OOP)
-
可移植性,一次编译,到处运行
-
健壮性,自动垃圾回收机制(GC)
-
多线程
安装工具
- JDK:安装包,(JVM+JRE)
- JVM:Java虚拟机,(JVM+JRE),不改变程序前提下在两个不同的环境运行
- JRE:运行环境
三者关系:

编译运行
- . java文件,源文件,不能运行
- . class文件,字节码文件,检查语法
- 一个源文件(.java)可以生成一个或多个字节码文件(.class)
命名规则
- 包:com/pre(公司/个人).xxx(项目名).model(模块名)
- 类:首字母大写、由多个单词组成其他单词首字母大写
Java基础
基本输出
print、println、err.print / println
public static void main(String[] args) {
//输出
System.out.print("hello world");
//输出联想 -- sout
//println -- 换行输出
System.out.println("hello world");
System.out.println("hello world");
//err -- 错误输出显示红色 -- 没有缓冲,第一次运行第一个显示,此后都最后显示
System.err.println("hello world");
}
运行结果

输出规则
public static void main(String[] args) {
//双引号+字符串可看做字符串
System.out.println("a b");
//输出表达式不需要加双引号
System.out.println(1+2);
//字符串相加,”+“可看做为拼接符号
System.out.println("a"+"b");
//以字符串开头,后有表达式时,“+”为拼接符号(先算a+1,再算a1+2)
System.out.println("a"+ 1 + 2);
//以表达式开头,后有字母,前为运算符,后为拼接符
System.out.println(1 + 2 + "a");
}
运行结果

声明变量
- 变量:存储数据,一次只能存储一个数据
- 声明变量:变量类型 + 变量名
- 变量类型:ex 整型( int )、字符串( String )等
- 变量名命名规则:单词首字母小写,多个单词组成首字母第二个单词开始首字母大写,不能使用关键字
- 变量名组成:大小写字母,下划线、数字、$符组成(不建议超长变量名)
public static void main(String[] args) {
int a = 1;
String smallRedCat = "hello";
System.out.println(a);
System.out.println(smallRedCat);
}
运行结果

数据类型
数据类型分为基本数据类型、引用类型
- 基本数据类型(8种):整型类型(byte、short、int、long)、浮点类型(float、double)字符类型(char)布尔类型(boolean)
- 引用类型:类、接口、数组
强制类型转换
//小类型与大类型进行运算时需要强制类型转换
short s1 = 1;
short s2 = (short)(s1+1);
float f1 = (float) 8.8;
//大类型与小类型计算不需要强制类型转换
short t1 = 1;
int t2 = t1 + 1;
double f2 = 8.8F;
数据大小
整数类型
- byte 长度8位,占1个字节范围:-128~127
- short 长度16位,占2个字节范围:-32768~32768
- int 长度32位,占4个字节范围:-2147483648~2147483648
- long 长度64位,占8个字节范围:-92233372036854775808~92233372036854775808
PS: long类型使用时要在数字后加个L ( ex: long a = 10L; ),手机号、邮编、身份证号不参与计算的数字不定义为整型类型。
浮点类型
- float 长度32位,占4个字节
- double 长度64位,占8个字节
PS: float类型使用时要在数字后加个F ( ex: float a = 10.4546F; )。
字符类型
- char 长度16位,占2个字节(默认值/u0000)
- 如果不输入单引号,直接输入数字,则按照ASCII码对照输出
PS: char类型只能赋值一个字符(例如'A'、'中'...),如果想赋值一句话可以使用String类型(string a = "Hello , world ! "),java中汉子、字母、字符、数字都占2个字符。
boolean类型
- 长度8位,占1个字节,其值只有TRUE或FALSE(默认值FALSE)
引用类型
-
类
-
接口
-
数组
基础运算
基础运算
public static void main(String[] arg){
//算术运算符:+、-、*、/、% ; 加、减、乘、除、取余
int num = 10;
num = num + 5;
System.out.println(num);
num = num - 5;
System.out.println(num);
num = num * 2;
System.out.println(num);
num = num / 2;
System.out.println(num);
num = num % 3;
System.out.println(num);
}
运算结果

运算细节
public static void main(String[] arg){
//取整,舍掉小数后不会四舍五入
num = (int)(num+1.45);
System.out.println(num);
//浮点类型与整型做乘法,先计算,结果取整
int i = (int)(2.6*2);
System.out.println(i);
//除法运算0不可以作为除数,机器无法自动辨识,只有人工干预或者手写代码判断
double ero = 9.9/0.0;
System.err.println(ero);
}
运算结果

拆分数字
取余拆分数字操作
public static void main(String[] arg){
//两位数
int number = 98;
//求个位
int ge = number%10;
//求十位
int shi = number/10;
System.out.println("个位数是" + ge +"十位数是" + shi);
//三位数
System.out.println("987的个位数是" + 987%10);
System.out.println("987的个位数是" + (987/10)%10);
System.out.println("987的百位数是" + 987/100);
运算结果

自加运算
++num & num++
public static void main(String[] arg) {
int num = 1;
int result01 = num++;
System.out.println("num = " + num + " ,result01 = " + result01);
num = 1;
int result02 = ++num;
System.out.println("num = " + num + " ,result02 = " + result02);
num = 1;
int result03 = (num++) + (num++);
System.out.println("num = " + num + " ,result03 = " + result03);
num = 1;
int result04 = (++num) + (++num);
System.out.println("num = " + num + " ,result04 = " + result04);
num = 1;
int result05 = (num++) + (++num);
System.out.println("num = " + num + " ,result05 = " + result05);
}
运算结果

自加强转
short s1 = 1;
s1 = (short)(s1 + 1); //运算过程自动强制类型转换
short s2 = 1;
s2 += 1 //运算过程自动强制类型转换
转义符
\t 、 \r、\n...
public static void main(String[] arg) {
//字符\t----tab
System.out.println("a" + "\t" + "b");
//字符\r----回车,换行后到居中位置
System.out.println("a" + "\r" + "b");
//字符\n----回车,换行后到开头位置
System.out.println("a" + "\n" + "b");
}
运行结果

运算符
关系运算符
与或非
- && (短路与/逻辑与)
- || (短路或/逻辑或)
- & (与)
- | (或)
- ! (非)
public static void main(String[] arg) {
//关系运算符-----与或非---&&(短路与/逻辑与)---||(短路或/逻辑或)---!(非)---&(与)---|(或)
//&&---全正确(true),有错(false),全错(false)
System.out.println(6>2 && 8<9);
System.out.println(6<2 && 8<9);
System.out.println(6<2 && 8>9);
//||---全正确(true),有对(true),全错(false)
System.out.println(6>2 || 8<9);
System.out.println(6<2 || 8<9);
System.out.println(6<2 || 8>9);
//!=---全正确(false),有对有错(true),全错(false),单独使用取反
System.out.println(6>2 != 8<9);
System.out.println(6<2 != 8<9);
System.out.println(6<2 != 8>9);
System.out.println(!(6<2));
//&全部判断后输出,&&先判断前面,false后不再往后判断,前段正确后段有异常,&会终止,&&不会终止,进行下一步操作
String num = null;
System.out.println(5<2 & num.equals("a"));
System.out.println(5<2 && num.equals("a"));
//|---全正确(true),有对有错(true),全错(false)
System.out.println(6>2 | 8<9);
System.out.println(6<2 | 8<9);
System.out.println(6<2 | 8>9);
//|全部判断后输出,||先判断前面,true后不再往后判断,前段正确后段有异常,|会终止,||不会终止,进行下一步操作
System.out.println(5>2 | num.equals("a"));
System.out.println(5>2 || num.equals("a"));
}
运行结果
&报错

&&未报错

|报错

||未报错

总结
&---&&
- 单与(&) 判断时,只有全对才可以为 真,全部判断后才结束判断
- 双与(&&) 判断时,只有全对才可以为 真,只要有 错 直接结束该判断
|---||
- 单或( | ) 判断时,只要 有对的 就可以为 真,全部判断后才结束判断
- 双或( || ) 判断时,只要 有对的 就可以为 真,只要有 对 直接结束该判断
& --- | --- && --- ||
- 单与、单或进行判断时,如果判断条件出错,直接报错
- 双与、双或或进行判断时,达成判断条件,不管其之后的判断条件是否出错,退出本条判断,程序继续运行
比较运算符
- '>' : 大于
- '<' :小于
- '>=' :大于等于
- '<=' :小于等于
- '=' :赋值
- '==' :比较
- '===' :恒等于
public static void main(String[] arg) {
//比较运算符----->、<、>=、<=、==、!=
System.out.println(7>1);
System.out.println(7<1);
System.out.println(7>=1);
System.out.println(7<=1);
System.out.println("你好"=="你好");
String str = "你好";
System.out.println(str == "你好");
//== 比较地址 , new String 创建地址,所以每次地址不同,即使内容一致,地址不同,显示也为false
String str1 = new String("你好");
System.out.println(str1 == "你好");
//用equals()方法比较值,并非比较地址,基本数字类型不能调用方法,只能使用==,前后比较顺序需要注意
System.out.println(str.equals("你好"));
//equals方法导致空指针异常(解决方法:把已知的、有值的参放在前面)
String ero = null;//遇到实例时,变量是不会一成不变的,再用equals方法需要注意逻辑问题
System.out.println("你好".equals(ero));
//正常equals方法大小写敏感
System.out.println("a".equals("A"));
System.out.println("a".equalsIgnoreCase("A"));
}
运行结果

- 如果将空值比较中的变量 ero 放在前面(ero.equals("你好")),则程序报错 (空指针异常)
随机数
Math.random();获取随机数(double类型的0.1到1.0前闭后开的随机浮点数)
public static void main(String[] args) {
//随机数 Math.random();
//可以获取[0.1,1.0)的double类型的值
System.out.println(Math.random());
//获取[0,10]区间的整型随机数
//取值[0,11),即取值0~10
int num0 = (int)(Math.random()*11);
System.out.println(num0);
//[0,100] --- 因为取值前闭后开所以为[0,101)
int num1 = (int)(Math.random()*101);
System.out.println(num1);
//[10,15]
int num2 = (int)(Math.random()*6+10);
System.out.println(num2);
//[a,z]
int num3 = (int)(Math.random()*26+97);
char zm = (char)num3;
System.out.println(zm);
//[A,Z]
int num4 = (int)(Math.random()*26+65);
char ZM = (char)num4;
System.out.println(ZM);
}
运行结果

三目运算
- result = <判断式> ? <结果一> : <结果二>
- 如果 判断式 为真,则 result 赋值为 结果一
- 如果 判断式 为假,则 result 赋值为 结果二
public static void main(String[] args) {
int r1 = 4>6 ? 1:0;
boolean r2 = 4>6 ? true:false;
System.out.println(r1);
System.out.println(r2);
int a = 10,b=30;
// a 大于 b ? 是 赋值 a : 不是 判断(a==b)为真 ? 为真 赋值 0 : 为假 赋值 b
int r3 = a>b ? a:(a==b) ? 0:b;
System.out.println(r3);
}
运行结果

执行顺序
- 条件运算符 优先于 赋值运算符 所以在执行 += 等情况时会出现 语法错误
// 错误情况 --- 条件运算符 与 赋值运算符 并用出错
a>b ? a-=b : a+=b;
// 错误原因 --- 上式子等价于以下情况:
(a>b ? a-=b : a)+=b;
// 更正方法 --- 使用 括号 对内部的表达式进行区分
(a>b) ? (a-=b) : (a+=b);
三目运算执行顺序参考于 : http://c.biancheng.net/view/792.html
输入类
scanner类输入
public static void main(String[] args) {
//用户输入 Scanner类(java5之后才有的特征)
//scanner需要导入java.util.scanner包,idea会自动导入,
Scanner in = new Scanner(System.in);
//提示语
System.out.println("请输入年龄");
int age = in.nextInt();
System.out.println("请输入姓名");
String name = in.next();
System.out.println("请输入成绩");
double score = in.nextDouble();
System.out.println(age + " 岁的 " + name + " 的成绩为 " + score);
}
运行结果

注意如果 输入的类型 与 定义的类型 有出入,则有可能会导致程序报错(输入不匹配异常)
分支语句
if 语句
- if ( 判断条件 ) else if ( 此判断条件之前判断都为 false 后执行此判断 ) ... else
简单练习
- 简易的用户名密码问题:定义用户名,密码,使用 if else 判断是否通过
- 简易比大小问题:控制台输入两数,比较其大小
public static void main(String[] args) {
//模拟用户输入用户名密码
Scanner in = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = in.next();
System.out.println("请输入密码:");
String passwd = in.next();
if("admin".equals(username) && "123".equals(passwd))
{
System.out.println("输入正确,登陆成功!");
}
else if (!"admin".equals(username) || !"123".equals(passwd))
{
System.out.println("用户名或密码不正确");
}
//比大小
System.out.println("请输入第一个数");
int num1 = in.nextInt();
System.out.println("请输入第二个数");
int num2 = in.nextInt();
if(num1>num2)
{
System.out.println(num1 + ">" + num2);
}
else if (num1<num2)
{
System.out.println(num1 + "<" + num2);
}
else
{
System.out.println("两数相同");
}
}
运行结果
用户名密码正确

用户名不正确密码正确

用户名正确密码不正确

比大小

Switch语句
switch case 分支语句
- switch --- case --- break --- default
- break 结束当前语句 ;(continue --- 结束本次循环返回上层进行下次循环)
- default 没有符合内容时输出内容
switch 判断值类型
-
switch 可以存放类型为 byte 、 short 、 int 、 char 、String ;
-
switch 中可以存放String类型内容(Java5后都可以)
switch 与 if
一般情况下 switch 用作判断,与 if 效果相似,两者使用时具体因实例而定选择合适的分支语句。
举例
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
System.out.println("请输入1-3的数字");
int num = in.nextInt();
switch (num)
{
case 1:
System.out.println("输入的是1");
break;
case 2:
System.out.println("输入的是2");
break;
case 3:
System.out.println("输入的是3");
break;
default:
system.out.println("您的输入超过范围了");
}
}
运行结果

循环语句
- for
- while
- dowhile
- foreach
for 循环
for ( 起始循环数 ; 循环范围 ; 递增 / 递减 )
有限循环
public static void main(String[] args)
{
//for 循环
for(int i = 0; i < 10 ; i++)
{
System.out.println(i);
}
}
运行结果

无限循环
- for ( ; ; ) --- 控制台/代码退出
- for ( int i ; ; i++ ) --- 控制台/代码退出
- 循环体中根据程序情况 添加 退出循环的判断条件,否则为死循环 ,for 循环之后的代码无法运行,只能从控制台控制结束程序
for(int i = 0; ; i++)
{
if(i==100)
break;
}
比较
- 情况一:当循环中 不 需要 计数 时,使用for ( ; ; )更方便
- 情况二:当循环中 需要 计数 时,使用for ( int i ; ; i++ )更方便
while 循环
while (boolean型值 / 判断表达式) { 循环体 }
有限循环
- 设置初值,给定范围,进入循环
int i = 2;
while (i<5)
{
i++;
System.out.println(i);
}
无限循环
- while (true)
- 循环体中根据程序情况 添加 退出循环的判断条件,否则为死循环 ,while 循环之后的代码无法运行,只能从控制台控制结束程序
int i=0;
while(true)
{
i++;
System.out.println(i);
if(i == 100)
{
break;
}
}
dowhile 循环
- 相比较 while ,dowhile 先执行 代码段 后 判断
有限循环
- do { 循环体 } while( 判断体 )
int j =0;
do {
j++;
System.out.println(j);
}while (j<10);
无限循环
- do { 循环体 } while ( true )
int i = 0;
do{
System.out.println(++i);
//if(i == 10){break;}
}while(true);
循环体中根据程序情况 添加 退出循环的判断条件,否则为死循环 ,dowhile 循环之后的代码无法运行,只能从控制台控制结束程序
foreach 循环
多用于数组遍历
int []arr = new int[10];
for(int num : arr)
System.out.println(num);
数组
一维数组
数组
- 引用类型
- 可看成容器,存储多个单一类型的数据
- 定长,必须要给数组初始长度。
创建数组
- 数据类型 [ ]数组名 = new 数组类型[ 数组长度 ]
int []arr1 = new int[10];
double []arr2 = new double[10];
char []arr3 =new char[10];
//C 的写法 , java中这么写不算错,但是为了格式正确美观,最好按照标准写
int arr11[] = new int[10];
//给定初始值,数组初始长度位初始值数量
int arr111[] = {1,2,3,4,5,6};
赋值取值
- 利用下标赋值、取值
- 数组默认值 int --- 0 ; double --- 0.0 ; char u/0000 ; String --- null ;
- 数组下标从0开始
- 取数组长度 --- 数组名 . length
//赋值
arr1[0] = 123;
arr1[1] = 456;
arr1[2] = 789;
//取值
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(arr1[2]);
//取数组长度
System.out.println(arr1.length);
//取数组所有值
for(int i = 0; i < arr111.length; i++)
{
System.out.println(arr111[i]);
}
//foreach遍历
for(int num : arr111)
System.out.println(num);
二维数组
定义&赋值
-
数据类型 【】【】数组名 = new int【长度】【长度】
-
arr . length = 多维数组中的单数组数
int [][]arr = new int[2][3];
int [][]array = {{2,6,9},{6,7,5},{1,5,3}};
输出
foreach 方法遍历
for(int []a : array)
{
for (int b : a)
System.out.print(b + "\t");
System.out.println();
}
for 方法遍历
for(int i = 0; i < array.length; i++)
{
for (int j = 0; j < array[i].length; j++)
System.out.print(array[i][j] + " ");
System.out.println();
}
运行结果

排序
foreach
int [][]array1 = new int[2][5];
for(int i = 0; i < array1.length; i++)
{
System.out.println("请输入第 "+ (i+1) +" 个数组的元素[最大不要超过5个数]:");
//输入
for (int j = 0; j < array1[i].length; j++)
{
array1[i][j] = in.nextInt();
}
}
for(int []a : array1)
{
//排序
Arrays.sort(a);
for(int b : a)
System.out.print(b + " ");
System.out.println();
}
for
int [][]array1 = new int[2][5];
for(int i = 0; i < array1.length; i++)
{
System.out.println("请输入第 "+ (i+1) +" 个数组的元素[最大不要超过5个数]:");
//输入
for (int j = 0; j < array1[i].length; j++)
array1[i][j] = in.nextInt();
System.out.println();
}
for(int i = 0; i < array1.length; i++)
{
//排序
Arrays.sort(array1[i]);
for (int j = 0; j < array1[i].length; j++)
System.out.print(array1[i][j] + " ");
System.out.println();
}
运行结果

排序
- sort()
- 递归排序
- 选择排序
- 插入排序
- 冒泡排序
- 顺序排序
这里只列举 sort 和 冒泡 排序
sort方法
Arrays . sort . ( 数组 )
int []arr = {1,5,3,6,7,4,9,2,8};
//默认从小到大排序
Arrays.sort(arr);
for (int n : arr)
System.out.print(n + " ");
System.out.print("\n");
//从大到小输出
for(int i = arr.length-1; i>=0; i--)
System.out.print(arr[i] + " ");
运行结果

冒泡排序
- 默认从小到大
- 两两比较
运行方式

- 如果想从大到小排序,两值对比时为 <
- 如果想从小到大排序,两值对比时为 >
代码
public static void main(String[] args) {
int []array = {6,5,4,3,2,1};
//循环 排序遍数
for(int i = 0; i < array.length-1; i++)
{
//循环 每一遍的比较次数
for(int j = 0; j < array.length-1-i; j++)
{
//判断大小,a[i]>a[i+1],从小到大;a[i]<a[i+1],从大到小
if (array[j] > array[j + 1])
{
//创建占值变量
int tmp = array[j];
//互换值操作
array[j] = array[j+1];
array[j+1] = tmp;
}
}
}
//排序结束,输出结果
for(int n : array)
System.out.print(n + " ");
}
运行结果

方法
- C --- 函数
- java --- 方法
修饰符 访问方式 返回值 方法名(参数列表){方法体}
ex:
- 修饰符:public
- 访问方式:static
- 返回值:void
- 方法名命名:首字母小写,后跟单词首字母大写
public class Study_Method {
public static void test(){
System.out.println("没有返回值的静态方法");
}
public void test(){
System.out.println("没有返回值的普通方法");
}
public static int test(){
System.out.println("返回值为int类型的静态方法");
return 8;
}
public void test(String str){
System.out.println("有形参的普通方法");
}
}
方法调用
- 创建对象 : 类名 自定义对象名 = new 构造方法(与类名相同)
- 对象调用 : 对象名 . 方法名(实参);
public static void main(String[] args) {
Method user = new Method();
user.test1();
user.test2();
int a = user.test3();
System.out.println(a);
user.test4("123");//多参时,注意参数列表顺序
}
运行结果

方法重载
- 方法名相同
- 参数列表不同(数量不同、类型不同、顺序不同)
- 方法重载与返回值无关
参数顺序不同是在参数类型不同前提下进行判断
public void f(int a,int b){}
public void f(int b,int a){}
如上两个方法会判定为同一方法
方法重载ex:
public static void test(int a, String b){}
public void test(int a, int b){}
public void test (String a, int b)
ps:重载和重写不同,重写为子类重写父类方法
静态方法
特点
- 静态方法与主方法在同一类中可以只写方法名调用
- 不在同一类中,以 类名.方法名();使用
调用方式
- 创建对象
- 类名调取
public class C1 {
public static void test1(){
System.out.println("C1");
}
}
public class C2 {
public static void test2(){
System.out.println("C2");
}
public static void main(String[] args) {
//其他类的方法调用
C1.test1();
C1 user1 = new C1();
user1.test1();
//本类中的方法调用
test2();
C2.test2();
C2 user2 = new C2();
user2.test2();
}
}
运行结果

变量
- 静态成员变量 --- 全局变量 --- 属性 --- 一般可以不设初值,默认为该类型初值
- 成员变量 --- 全局变量 --- 属性 --- 一般可以不设初值,默认为该类型初值
- 局部变量 --- 一般情况需要设初值,否则无法参与运算
- 作用范围 静态成员变量从属于类 --- 成员变量从属于对象 --- 局部变量从属于方法
- 可看做 静态成员变量 优于 成员变量 优于 局部变量
普通方法中不能定义静态方法;静态方法中不能定义静态方法。
public class C1 {
//成员变量: 在类中定义的变量
//成员变量 --- 属性 --- 全局变量
public int id;
public String name;
//静态成员变量
public static double score;
public void f(){
//局部变量
String A = null;
}
}
成员变量调用方法
- 创建对象,调用
C1 user = new C1();
user.id = 10;
静态成员变量调用
- 创建对象,调用
- 类名调用
- 静态成员变量 和 主方法 在同一个类中可以直接使用变量名取值和赋值
C1 user = new C1();
user.id = 10;
C1.id = 10;
id = 10;
当局部变量和成员变量重名时:
public class C1 {
public int in = 80;
int id = 90;
public void f(){
System.out.println(id);
}
public static void main(String[] args) {
C1 user = new C1();
user.f();
}
}
运行结果

就近原则选择了局部变量的值
静态变量与方法
静态方法 可以调用 静态成员变量
普通方法 可以调用 静态成员变量 ,成员变量

构造方法
-
和类名相同,并且没有返回值,不被void修饰的方法
-
一个类创建后会有默认的无参构造方法
-
构造方法 --- 构造函数
-
创建有参构造方法后,默认无参构造方法会被回收
-
形参与成员变量同名时需要添加this区分
public class C1{
public C1(){
//无参构造方法
System.out.println("无参构造方法");
}
public static void main(String[] args) {
C1 user = new C1();
}
@Override
public String toString(){
return "C1{" +
"id=" + id +
",name-" + name + "\'" +
"}";
}
}
/*================================================*/
public class C1{
int id;
String name;
public C1(int id, String name){
//有参构造方法
this.id = id;
this.name = name;
}
public static void main(String[] args) {
C1 user = new C1(90,"张三");
System.out.println(user);//想要输出user成员,idea需要右键点击生成,tostring即可
}
}
运行结果

封装
- 将成员变量私有化:private
- 类内实现可以使用对象直接赋值取值,也可以使用set和get方法
- 类外实现只能使用get和set方法
特点
- 隐藏信息,实现细节
- 对成员变量更精准的控制
- 类内部结构自由修改
- 减少耦合、联系、依赖
- 独立性差
public class Study_private {
private int id;
private String name;
private double money;
public int getId() {
return id;
}
//右键→生成→Getter和Setter
//set方法赋值,get方法取值
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
Study_private p = new Study_private();
p.id = 90;
p.name = "张三";
System.out.println(p.id+p.name);
p.setId(10);
p.setName("李四");
System.out.println(p.getId()+p.getName());
}
}
public class Getnum {
public static void main(String[] args) {
Study_private p = new Study_private();
p.setId(90;
p.setName("张三");
System.out.println(p.getId()+p.getName());
}
}
继承
- public class son extend father {}
- 子类可以继承父类中的成员变量和除构造方法以外的其他方法
- 子类可以新增属于自己的方法和成员变量,父类不能访问到子类属性和方法
- 孙类(子类的子类)可以通过继承子类的内容间接继承到父类的内容
/*===================Father===================*/
public class Father {
private String Fname = "父亲";
private int Fage = 40;
public String getFname() {
return Fname;
}
public void setFname(String fname) {
Fname = fname;
}
public int getFage() {
return Fage;
}
public void setFage(int fage) {
Fage = fage;
}
public void Flike(){
System.out.println("父亲喜欢喝酒");
}
}
/*====================Son=====================*/
public class Son extends Father{
private String Sname = "儿子";
private int Sage = 18;
public String getSname() {
return Sname;
}
public void setSname(String sname) {
Sname = sname;
}
public int getSage() {
return Sage;
}
public void setSage(int sage) {
Sage = sage;
}
public void Slike(){
System.out.println("儿子喜欢打游戏");
}
//方法重写,重写后使用子类对象访问的就是子类的方法
public void Flike(){
System.out.println("儿子知道父亲喜欢喝酒");
}
}
/*==================Grandson==================*/
public class GrandSon extends Son{
private String Gname = "孙子";
private int Gage = 1;
public String getGname() {
return Gname;
}
public void setGname(String gname) {
Gname = gname;
}
public int getGage() {
return Gage;
}
public void setGage(int gage) {
Gage = gage;
}
public void Glike(){
System.out.println("孙子喜欢的是奶瓶");
}
}
/*====================Test===================*/
public class Test {
public static void main(String[] args) {
//子类测试
Son s = new Son();
System.out.println(s.getFname());
System.out.println(s.getSname());
s.Flike();
s.Slike();
//孙类测试
GrandSon g = new GrandSon();
g.Glike();
g.Slike();
g.Flike();
System.out.println(g.getFname());
}
}
重写前

重写后

孙类调用子类与父类内容

super
super()使用
- super : 调取父类的无参构造方法
- super()方法必须在构造方法的第一行
- 子类默认构造方法中,默认调取super();可省略
- 子类有参构造方法中,可以调取有参super方法给父类成员赋值
- 如果父类已封装,那么无法在子类默认构造方法调取父类有参构造方法
- 子类无参构造只能调取父类中的无参构造(super可省略),子类有参构造可调取父类有参构造和无参构造(默认调取无参,需加入有参super)
super . 使用
- 可以使用super . 调取父类的非私有的成员变量、方法
- 调取父类成员、方法,不用放在首行
/*========================父类========================*/
public class SuperFather {
private int fId;
public int getfId() {
return fId;
}
public void setfId(int fId) {
this.fId = fId;
}
public SuperFather() {
}
public SuperFather(int fId) {
this.fId = fId;
}
}
/*========================子类========================*/
public class superSon extends SuperFather{
private int sId;
public int getfId() {
return sId;
}
public void setfId(int fId) {
this.sId = fId;
}
public superSon(){
//调取父类无参构造方法,super()必须在方法中第一行
super();
//调取父类成员
super.getfId();
}
public superSon(int fId) {
//调取父类有参构造,super()必须在方法中第一行
super(15);
//调取父类成员
super.getfId();
}
}
this
调取构造方法
- 必须写在构造方法中的第一行
- 无参构造中调取了this(参数),那么有参构造不能用this()方法了
- 无参构造中只可以利用this调取有参构造,不能自己调取自己,反之同理
调取本类的成员变量
- this . 调取成员变量
public class Study_This {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Study_This(int id){
//调取无参构造
this();//赋值为无参调取有参操作,需在无参构造中进行
//调取本类成员
this.id = id;
//调取本类方法
this.getId();
}
public Study_This(){
//有参调无参,无参调有参,二者取其一
//this(15);
}
}
权限修饰符
- public : 公开的 ,本类可直接访问 ,包内可以直接访问 ,项目中其他包可直接访问
- protected : 受保护的,本类可直接访问,本包内可以直接访问,跨包访问(继承关系)
- default : 缺省的 ,本类可直接访问 ,本包可以直接访问
- private : 私有的 ,本类可直接访问
Final关键字
- 被final修饰的类不可以被继承
- 被final修饰的变量必须赋初值,且不可更改(此变量成为常量,常量命名:所有字母全部大写)
- 被final修饰的方法不可以被重写
多态
多态定义
- 一种事物的多种形态
多态条件
- 继承关系
- 子类必须重写父类的方法
多态
- 调取方法时,需注意哪个是创建类,除去重写的内容,其余全使用创建类内容
/*==================父类==================*/
public class Animal {
public void eat(){
System.out.println("动物需要吃东西");
}
}
/*==================子类==================*/
public class Cat extends Animal{
public void play(){
System.out.println("猫喜欢玩球");
}
public void eat(){
System.out.println("猫喜欢吃鱼");
}
}
/*==================测试==================*/
Animal a = new Animal();
Cat c = new Cat();
c.eat();
a.eat();
//多态:1.继承关系 2.子类必须重写父类的方法
Animal a1 = new Cat();
a1.eat();
}
}
运行结果

向下转型风险与避免
向下转型:
public class AnimalTest {
public static void main(String[] args) {
Animal a = new Animal();
Cat c = new Cat();
c.eat();
a.eat();
//多态:1.继承关系 2.子类必须重写父类的方法
Animal a1 = new Cat();
a1.eat();
//向下转型(需要强制转换,有风险)
Cat c2 = (Cat) a;//报错
//Cat c2 = (Cat) a1;//正常
c2.eat();
}
}
运行结果

解决方法
- 做判断,判断对象是否包含、属于一个类
- 使用 instanceof :和比较运算符属于一个类,唯一不同的是它单词,二院操作符
public class AnimalTest {
public static void main(String[] args) {
Animal a = new Animal();
Cat c = new Cat();
c.eat();
a.eat();
//多态:1.继承关系 2.子类必须重写父类的方法
Animal a1 = new Cat();
a1.eat();
//向下转型(需要强制转换,有风险)
//Cat c1 = (Cat) a1; ..有风险,进行风险判断
//向下转型判断
if(a1 instanceof Cat){
Cat c1 = (Cat) a1;
c1.eat();
}
else{
System.out.println("a1不属于Cat");
}
//向下转型判断
if(a instanceof Cat){
Cat c2 = (Cat) a;
c2.eat();
}
else{
System.out.println("a不属于Cat");
}
}
}
运行结果

抽象
- abstract : 修饰类、方法
- 抽象类不一定有抽象方法,抽象方法一定要定义在抽象类中
- 抽象方法 : public abstract void xxx(); ,没有方法体
public abstract class Study_abstract {
private int a;
private String name;
public Study_abstract(){
System.out.println("构造方法");
}
public abstract void abc();
public static void main(String[] args) {
//无法抽象类实例化
//Study_abstract s = new Study_abstract();
}
}
public class Test_abstract extends Study_abstract{
//子类继承抽象类,必须重写抽象方法
@Override
public void abc() {
System.out.println("run");
}
public static void main(String[] args) {
Test_abstract t = new Test_abstract();
t.abc();
}
}
代码块
- 普通代码块,会随着摆放位置优先级发生变化,优先级不固定
- 构造代码块,在类中直接写方法体的代码块
- 静态代码块,static{} ,优先级最高
- 静态代码块 > 构造代码块 > 构造方法
- 多次运行时静态代码块只运行一次,其余会随着优先级依次运行
public class Kuai {
//代码块
public Kuai(){
System.out.println("构造方法");
}
//将方法的方法体拿出单独使用,称为代码块
{
//直接卸载类中的代码块成为构造代码块
System.out.println("构造代码块");
}
//静态代码块
static {
System.out.println("静态代码块");
}
}
public class Test_kuai {
public static void main(String[] args) {
//写在方法中的的代码块,称为普通代码块
{
System.out.println("普通代码块");
}
//实例化代码块对应的类
Kuai k =new Kuai();
//再次实例化
Kuai k1 =new Kuai();
}
}
第一次实例化

第二次实例化

- 发生继承关系时,运行顺序出现变化
- 父类静态代码块>子类静态代码块>父类构造代码块>父类构造方法>子类构造代码块>子类构造方法
- 同样的,静态代码块只运行一次
public class Kuai {
//代码块
public Kuai(){
System.out.println("父类构造方法");
}
//将方法的方法体拿出单独使用,称为代码块
{
//直接卸载类中的代码块成为构造代码块
System.out.println("父类构造代码块");
}
//静态代码块
static {
System.out.println("父类静态代码块");
}
}
public class Test_kuai extends Kuai{
public Test_kuai(){
System.out.println("子类构造方法");
}
//将方法的方法体拿出单独使用,称为代码块
{
//直接卸载类中的代码块成为构造代码块
System.out.println("子类构造代码块");
}
//静态代码块
static {
System.out.println("子类静态代码块");
}
public static void main(String[] args) {
//继承关系
Test_kuai t = new Test_kuai();
//第二次实例化
Test_kuai t1 = new Test_kuai();
}
}
第一次实例化

第二次实例化

接口
成员变量的变化
- 只能被 缺省 和 public 修饰
- 默认被 final 和 static 修饰,相当于常量,必须给初始值
方法的变化
- 接口中不能定义普通方法
- 接口中可以定义静态方法
- 接口中没有构造方法,接口不能实例化
- 接口中定义抽象方法时可以省略 abstract
代码块的变化
- 不能定义构造代码块
- 不能定义静态代码块
public interface I1 {
//只能被缺省和public修饰
//接口中默认被final修饰,必须给初始值
int id = 10;
public String name = null;
//不可定义普通方法
public static void a(){
System.out.println("静态方法");
}
//接口中定义抽象方法可以省略abstract
public abstract void b();
public void c();
public default void d(){}
}
因被 final 和 static 修饰,所以可以用以下方法调取:
- 接口名调取
- 实现类名调取
- 实现类的对象调取
- 接口的静态方法只能选择接口名直接调取
接口的实现类( implements )
- 实现类可以多实现
- 实现类必须重写接口的抽象方法
- 接口的实现类如果又想作为接口实现类、又想作为继承类时,先继承再实现
- 接口若继承了其父接口的抽象类,接口的实现类需要将其父接口的抽象类也写出来
//实现类
public class C2 implements I1{
@Override
public void b() {
System.out.println("b的实现");
}
@Override
public void c() {
System.out.println("c的实现");
}
}
//主函数
public class C3 {
public static void main(String[] args) {
C2 t = new C2();
t.b();
t.c();
System.out.println(I1.id);
System.out.println(C2.id);
System.out.println(t.id);
I1.a();
}
}
//继承实现类
public class C3 extends C2 implements I1{
//方法体
}
运行结果

数组 & 类
public class Student{
private int id;
private String name;
private double score;
private String sex;
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public double getScore(){
return score;
}
public void setScore(double score){
this.score = score;
}
public String getSex(){
return sex;
}
public void setSex(String sex){
this.sex = sex;
}
public Student(){
id =1;
name = "张三";
score = 99;
sex = "男";
}
public Student(int id,String name,double score,String sex){
this.id = id;
this.name = name;
this.score = score;
this.sex = sex;
}
}
public class Arrstu{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
Student []stu = new Student[5];
Student s =null;
for(int i = 0; i < stu.length; i++){
s = new Student(in.nextInt();in.next();in.nextDouble();in.next();)
stu[i] = s;
}
for(Student n : stu){
System.out.println(n);
}
}
}
类间关系
依赖关系
- 通过形参方式表现依赖关系
- 通过实例化方式表现依赖关系
- 通过类名直接调取静态方法表现依赖关系
/*======Pen======*/
public class Pen{
public static void write(){
System.out.println("写字");
}
}
/*======User=====*/
public class User{
public void user(Pen p){
//通过形参的方式表现依赖关系
p.write();
}
public void user(){
//通过实例化方式表现依赖关系
Pen p = new Pen();
p.write();
}
public void user(){
//通过类名直接调取静态方法表现依赖关系
Pen.write();
}
public static void main(){
Pen p = new Pen();
//实例化实现
User u = new User();
//形参方式
u.user(p);
//类名调取
u.user();
}
}
关联关系
- 成员变量形式表现关联关系
- 通过形参的形式表现关联关系
/*==============Car===============*/
public class Car{
public void car(){
System.out.println("车");
}
}
/*==============Driver============*/
public class Driver{
//关联关系(成员变量方式)
Car c;
public void driver(){
//通过成员变量形式表示关联关系 ---> 我拥有这辆车
c.car();
}
public void driver(Car c){
//通过形参的形式表现关联关系 ---> 车不是我的,我只是个司机,在使用车
c.car();
}
}
聚合关系
- 某一类是另一类的一部分(ex : 手是身体的一部分)
/*==============Driver============*/
public class Driver{
Car c;
public void driver(){
//通过成员变量的形式表现聚合关系 ---> 车是我财产的一部分
c.car();
}
}
组合关系
- ex:程序员开发程序需要用到电脑,电脑 --- 程序员 是组合关系
public class Driver{
public void driver(Car c){
//通过形参表现组合关系 ---> 司机载客需要车
c.car();
}
}
内部类
定义
- Java 中允许类中声明另一个类,另一个类成为内部类
分类
- 静态内部类
- 费静态内部类
- 成员内部类
- 局部内部类
- 匿名内部类
成员内部类
- 与成员变量同级关系
- 成员内部类不能定义静态成员
- 成员内部类不能定义静态方法
- 成员内部类通过外部类对象创建内部类对象
- 通过外部类构造方法调用内部类构造方法,创建内部类的对象
public class OutCheng{
int age =19;
//成员内部类,权限修饰符可以使用四个(protected, public, private, default)
protected class Inner{
int num = 10;
//static String name = null;内部类不可以定义静态成员变量
public void show(){
System.out.println("普通方法" + num);
}
/*public static void show2(){
成员内部类不能定义静态方法
}*/
}
}
public static void main(String[] args){
//成员内部类实例化方式,依赖外部类
//1.通过外部类对象创建内部类对象
OutCheng oc = new OutCheng();
oc.age = 19;
Inner in = oc.new Inner();
in.show();
in.num = 1;
//2.通过外部类的构造方法调用内部类的构造方法,创建内部类的对象
Inner in2 = new OutCheng().new Inner();
in2.show();
}
局部内部类
- 局部内部类和局部变量同级
- 通过方法内部自身调取内部类
-public class OutJu {
public void show(){
//局部变量
int id = 90;
//局部内部类(权限修饰符只能填缺省)
class Inner{
int did = 80;
public void f(){
int age;
//jdk1.8后对于局部内部类,局部变量相当于被final修饰的,只能调用不能修改
//id = 100;
System.out.println(id);
System.out.println("局部内部类的普通方法");
}
}
//通过方法内部自身调取内部类
Inner i = new Inner();
i.f();
}
public static void main(String[] args) {
OutJu oj = new OutJu();
oj.show();
}
}
静态内部类
- 被static修饰的内部类
- 静态内部类可以被四个权限修饰符修饰
- 静态内部类对于外部类的依赖较少
- 通过外部类对象调取静态内部类的方法
- 通过内部类类名调取静态方法、静态变量(外部类类名.内部类类名.静态方法)
/*============OutStatic============*/
public class OutStatic {
//静态内部类
//被static修饰的内部类
public static class Inner{
int id = 10;
private int age;
static String name = "张三";
public void f(){
System.out.println("普通方法");
}
public static void show(){
System.out.println("静态方法");
}
}
}
/*===============Test===============*/
public class Test_OutStatic {
public static void main(String[] args) {
OutStatic.Inner oi = new OutStatic.Inner();
//通过对象调取静态内部类的方法
oi.f();
oi.show();
//通过内部类类名调取静态方法、静态变量(外部类类名.内部类类名.静态方法)
OutStatic.Inner.show();
System.out.println(OutStatic.Inner.name);
}
}
匿名内部类
- 一般作用于接口或抽象类 --- 两者都不能实例化
- 匿名内部类只能被缺省(default)权限修饰
接口 --- 匿名内部类
/*==============接口===============*/
public interface OutNiInter {
//抽象方法
public void show();
}
/*==============实现===============*/
public class Test_Inter_OutNi implements OutNiInter{
@Override
public void show() {
}
public static void main(String[] args) {
OutNiInter oi = new OutNiInter() {
@Override
public void show() {
System.out.println("匿名内部类show方法");
}
};
oi.show();
}
}
抽象类 --- 匿名内部类
/*===================抽象类===================*/
public abstract class OutNi {
//抽象方法
public abstract void show();
}
/*====================实现====================*/
public class OutNiSon{
public static void main(String[] args) {
//匿名内部类只能被缺省权限修饰
class Son extends OutNi{
@Override
public void show() {
System.out.println("匿名内部类show方法");
}
}
Son s = new Son();
s.show();
OutNi ot = new Son();
ot.show();
}
}
枚举类
- jdk1.7后有的枚举类型,创建接口中的常量
- 常量定义使用全大写
/*====================Color====================*/
public enum Color {
//枚举类,用来做信息标志和分类,创建接口中的常量
//枚举类常量定义大写
RED,WHITE,BLUE,GREEN,BLACK,PINK
}
/*=====================Test====================*/
public class TestEnum {
public static void main(String[] args) {
//将字符串转换为枚举类型
Color c = Color.valueOf("RED");
//枚举类型
switch (c){
//RED等都已在枚举类型中定义好的常量
case RED:
System.out.println("红色");
break;
case WHITE:
System.out.println("白色");
break;
case BLUE:
System.out.println("蓝色");
break;
case GREEN:
System.out.println("绿色");
break;
case BLACK:
System.out.println("黑色");
break;
case PINK:
System.out.println("粉色");
break;
default:
System.out.println("error");
}
//取枚举类中所有常量
for(int i = 0; i < Color.values().length; i++){
System.out.println(Color.values()[i]);
}
for(int i = 0; i < Color.values().length; i++){
//查找枚举类中每个常量对应的索引值
System.out.println(Color.values()[i].ordinal());
}
//枚举类比较,用来比较的参数必须为枚举类中有的常量,否则会报错
Color c2 = Color.valueOf("GREEN");
for(int i = 0; i < Color.values().length; i++){
System.out.println ((Color.values()[i]) + " "+ Color.values()[i].compareTo(c2));
}
}
}
异常处理
错误 --- error
- 出错直接终止程序
异常 --- exception
- 异常可以捕捉,程序不需要修改也可以正常运行
- 异常分为编译异常、运行异常
共同点:两者都有一个一个共同的父类Throwable
编译异常
- 不符合语法,可以直观看到,需要解决
运行异常
- 编译正常,当程序运行时出现报错信息
异常处理使用
- try {} catch(){}
- try{}catch(){}catch(){}...
常见异常
- 算数异常
- 空指针异常
- 下标越界异常
//ArithmeticException 算数异常 ---> 除数为零
int num = 6/0;
//NullPointerException 空指针异常
String name = null;
name.charAt(0);
//ArrayIndexOutOfBoundsException 下标越界异常
int []arr = new int[3];
arr[3] = 90;
异常处理
- 算数异常 ArithmeticException
- 空指针异常 NullPointerException
- 下标越界异常 ArrayIndexOutOfBoundsException
- 父类异常 Exception
public class SolveError {
public static void main(String[] args) {
//try 将 容易发生异常的代码包住
//tyr 中出现异常时,其他代码不会被执行到,直接进行catch捕捉,捕捉到正常运行,没有捕捉到结束捕捉
try {
int []arr = new int[3];
arr[4] = 90;
System.out.println("123");
int num = 6/0;
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("下标越界");
}catch (Exception e){//多个异常捕捉时,异常父类(exception)需要放在最后捕捉
System.out.println("除数为零");
}
System.out.println("程序继续");
}
}
运行结果

注释掉第一个异常

try {}finally{}
- 不管是否程序出现异常,一定会执行finally,执行完终止程序,外面程序不会被执行
try {}catch(){}finally{}
public class SolveError {
public static void main(String[] args) {
//try finally
try {
String str = null;
str.charAt(0);
}finally {
System.out.println("程序报错了");
}
System.out.println("程序继续");
//try catch finally
try {
String str = null;
str.charAt(0);
}catch (NullPointerException e){
System.out.println("空指针异常");
}finally {
System.out.println("关闭资源");
}
System.out.println("程序继续");
}
}
运行结果

try catch finally

自定义异常
- 继承父类
throw
- 已经出现异常
- 抛出异常,在方法中跟异常对象名
- 一次只能抛出一个异常
throws
- 可能出现异常
- 声明异常
- 定义方法时后跟异常名,可声明多个异常,每个异常逗号隔开
public class OneException extend Exception{}
public class TwoException extend Exception{}
public class throwException{
public static void way(double a) throws OneException,TwoException{
if(a > 150){
throw new OneException();
}else if(f >= 140 && f <=150){
throw new TwoException();
}else{
System.out.println("It's OK.");
}
}
}
包装类
- 每个基本数据类型对应的引用类型
整型
- byte --- Byte
- short --- Short
- int --- Integer
- float --- Float
浮点
- double --- Double
- boolean --- Boolean
字符
- char --- Character
拆箱 装箱
- 拆箱 --- 将包装类转换成基本数据类型
- 装箱 --- 将基本数据类型转换成包装类
- 在-128~127区间内,Integer默认为基本数据类型。大于、小于这个区间时Integer会将内容自动装箱(new Integer)
public static void main(String[] args) {
int num = 90;
// 基本数据类型转换成包装类
Integer i = new Integer(90);
// 包装类转换成基本数据类型
Integer i2 = 78;
int n = i2;
//字符串转整型(字符串不能有字符或符号)
String str = "123";
//方法1
Integer i3 = new Integer(str);
System.out.println("i3");
//方法3
int i4 = Integer.parseInt(str);
System.out.println("i4");
//字符串转浮点(字符串不能有字符或符号)
String str2 = "10.15";
//方法1
Double i5 = new Double(str2);
System.out.println("i5");
//方法3
double i6 = Double.parseDouble(str2);
System.out.println("i6");
//字符串 转 布尔类型,字符串除了给true,其余无论给什么都是false
//转字符串
System.out.println(i3.toString());
}
Collection集合
- 变量 --- 存储一个数据
- 数组 --- 存储一组单一数据
- 集合 --- 容器,存储数据
- collection --- 集合中的父级别接口
- 子级 --- List集合 --- LinkedList 、 ArrayList (jdk1.2 , 线程不安全 ,性能好)、 Vector( jdk1.0 , 线程安全 , 性能较差)
- 子级 --- Set集合 --- HashSet
collocation父级接口定义
- Object --- 所有类的根父类
- 泛型:参数化类型 --- > (基本数据类型对于的包装类,引用类型)
public class StudyCollection {
public static void main(String[] args) {
Collection<Object> c = new ArrayList<>();
c.add(1);
c.add(true);
c.add(9.7);
c.add("abc");
/*for (int i = 0; i < c.size(); i++){
System.out.println(c.get(i));
} //不可行 */
//collection 无法通过索引取值,没有对应的get方法
System.out.println("集合长度" + c.size());
for(Object o : c){
System.out.println(o);
}
}
}
运行结果

List集合
ArrayList
- 可以存储重复数据
- 可以存储多个空值
- 超出索引范围,报下标越界异常
- 可以删除内容,(索引删除、数据删除(只删除一次))
public class StudyList{
public static void main(String[] args) {
//list集合 ---> ArrayList
//特点 可以存储重复数据、可以存储多个空值
//定义
List<Integer> list = new ArrayList<>();
//数据存储
list.add(1234);
list.add(null);
list.add(4561);
list.add(null);
list.add(65431);
list.add(4561);
//取值 --- 遍历
System.out.println("===========For==================");
for(int i = 0; i < list.size(); i++){
System.out.println(list.get(i));
}
System.out.println("===========Foreach==============");
for (Integer i : list){
System.out.println(i);
}
list.remove(4);
Integer num = 1234;
list.remove(num);
System.out.println("===========删除后==============");
for (Integer i : list){
System.out.println(i);
}
list.clear();
System.out.println("集合长度:" + list.size());
}
}
运行结果

链表式结构(LinkList)
- 需要导包(Java中只有long包不需要导包)
- 相比ArrayList多了addFirst 、 addLast 、 removeFirst 、 removeLast
public class StudyLinkList {
public static void main(String[] args) {
//java中只有lang包中内容不需要导包
//定义
LinkedList<Double> list = new LinkedList<>();
//赋值
list.add(11.11);
list.add(22.22);
//在指定位置添加
list.add(2,33.33);
//在开头插入
list.addFirst(0.0);
//在结尾插入
list.addLast(44.44);
//遍历
for(int i= 0; i < list.size(); i++){
System.out.println(list.get(i));
}
System.out.println("----------删除1----------");
//remove 不添加任何数据默认删除首位
list.remove();
//遍历
for(int i= 0; i < list.size(); i++){
System.out.println(list.get(i));
}
System.out.println("----------删除2----------");
//根据索引删除
list.remove(0);
//根据内容删除
list.remove(44.44);
//删除第一个
list.removeFirst();
//删除最后一个
list.removeLast();
//遍历
for(Double d : list){
System.out.println(d);
}
for(int i= 0; i < list.size(); i++){
System.out.println(list.get(i));
}
}
}
运行结果

LinkList --- ArrayList 比较
结构
- ArrayList 底层是数组
- LinkList 底层是链表式结构
效率
- ArrayList 检索读取速度快
- LinkList 添加删除效率快
总结:涉及的检索多时,选择ArrayList,涉及的添加删除多时,选择LinkList
Vector集合
- 基本淘汰,只做了解
Vector<Integer> v = new Vector<>();
v.add(10);//添加数据
v.remove(0);//通过索引和值进行删除
v.get(0);//通过索引取值
v.size();//集合长度
Set集合
- HashSet 实现类
- 无序排列,按照哈希算法排序
- 无法存储重复值
- 只能存储一个空值
- 无法使用索引插入
- 无法使用索引删除,只能按值删除
public class StudyHashSet {
public static void main(String[] args) {
//定义
Set<Integer> set = new HashSet<>();
//赋值
set.add(11);
set.add(22);
set.add(null);
set.add(33);
set.add(44);
set.add(55);
set.add(null);
set.add(66);
set.add(66);
//遍历(无法通过索引取值,即无法用for,只能用foreach)
System.out.println("集合长度:" + set.size());
for(Integer i : set){
System.out.println(i);
}
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next);
}
System.out.println("======删除======");
set.remove(null);
System.out.println("集合长度:" + set.size());
for(Integer i : set){
System.out.println(i);
}
System.out.println("======清空======");
set.clear();
System.out.println("集合长度:" + set.size());
for(Integer i : set){
System.out.println(i);
}
set.clear();
}
}
运行结果

List --- Set 比较
- List 有序 ,Set 无序
- List可以存储多个空值且可以存储重复值 , Set只能存储一个空值且不能存储重复值
Map集合
- List 、 Sat 属于 Collection,Map不属于
- 接口l类型
- 实现类:HashMap
- 无序的,键值对组成
- 赋值 key(可看做索引) 、value(数据)
- Key存储时不能重复,如果重复,则为覆盖数据
- Key可以存储一个空值,Value可以存储多个空值
- 遍历:foreach 简便方法 , 迭代器 , 迭代器以Key取值 , 迭代器直接取值 、foreach 多数据方法
- 数据量大的时候使用 foreach的多数据方法
public class StudyMap {
public static void main(String[] args) {
//定义
Map<Integer , String> map = new HashMap<>();
//赋值 8
map.put(1,"你好");
map.put(2,"Hello");
map.put(3,null);
map.put(null,"Wow");
map.put(5,"Bye");
map.put(256,"GB");
map.put(999,"Fan");
map.put(2,"Hi");
map.put(null,null);
//取值
System.out.println("----------Foreach----------");
for(Map.Entry<Integer , String> me : map.entrySet()){
System.out.println("Key: " + me.getKey() + " Value: " + me.getValue());
}
//迭代器输出法
Iterator<Map.Entry<Integer,String>> it = map.entrySet().iterator();
System.out.println("\n------------迭代器----------");
while(it.hasNext()){
Map.Entry<Integer,String> me = it.next();
System.out.println("Key: " + me.getKey() + " Value: " + me.getValue());
}
//迭代器根据Key取值
System.out.println("\n-------迭代器以Key取值-------");
Iterator<Integer> it2 = map.keySet().iterator();
while(it2.hasNext()){
Integer key = it2.next();
System.out.println("Key: " + key + " Value: " + map.get(key));
}
//迭代器直接取值
System.out.println("\n-------迭代器(取值)----------");
Iterator<String> it3 = map.values().iterator();
while(it3.hasNext()){
System.out.println(it3.next());
}
//foreach取值
System.out.println("\n-------foreach简便----------");
for(Integer num : map.keySet()){
System.out.println("Key: " + num + " Value: " + map.get(num));
}
System.out.println("\n------foreach多数据---------");
for(Map.Entry<Integer,String> me : map.entrySet()){
System.out.println("Key: " + me.getKey() + " Value: " + me.getValue());
}
}
}
运行结果

Iterator迭代器
- 用于遍历
- 迭代器泛型和需要遍历的集合泛型一致
public class StudyIterator {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(11);
list.add(22);
list.add(33);
list.add(44);
list.add(55);
Set<String> set = new HashSet<>();
set.add("abc");
set.add("123");
set.add("fan");
set.add("654");
set.add("happy");
//通过迭代器遍历
System.out.println("==========List=========");
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
Iterator<String> it2 = set.iterator();
System.out.println("==========Set==========");
while(it2.hasNext()){
System.out.println(it2.next());
}
}
}
运行结果

Collections工具类
- Collection --- 集合父级接口
- Collections --- 工具类 --- 一般用于对集合排序
- 不能应用于Set集合,Set集合使用哈希算法,无法用Collections排序
public class StudyCollections {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(11);
list.add(44);
list.add(33);
list.add(55);
list.add(22);
//排序
Collections.sort(list);
//倒序输出
for (int i = list.size()-1; i >= 0; i--){
System.out.println(list.get(i));
}
}
}
运行结果

集合总结
- List 、 Set 属于Collection接口下的,Map不是
- List 有序 ,Map 和 Set 无序
- List 可以存储重复数据,并可以存储多个 null
- Set只能存储一个 null 且不可以存储重复值
- Map 的 key 值不可以重复且只能存储一个 null , value 可以存储多个 null 且可以存储多个值


常用类
时间类
Date(已过时)
Date d = new Date();
- gettime() --- 返回自1970年1月1日 至今毫秒数
- toLocaleString() --- 返回当前年月日时分秒
- getYeat() --- 返回年份
- ...
Calendar(现用时间类)
public class StudyDate {
public static void main(String[] args) {
//定义
Calendar cal = Calendar.getInstance();
//取当前时间
System.out.println(cal.getTime());
//取年份 (cal.YEAR) --- 取当前中国时区的
System.out.println(cal.get(cal.YEAR));
//取月份 (月份从零开始(0~11),需要+1)
System.out.println(cal.get(cal.MONTH)+1);
//取日期
System.out.println(cal.get(cal.DATE));
//时
System.out.println(cal.get(cal.HOUR));
//分
System.out.println(cal.get(cal.MINUTE));
//秒
System.out.println(cal.get(cal.SECOND));
//周 (周日为第一天,所以获取星期需要-1)
System.out.println(cal.get(cal.DAY_OF_WEEK-1));
//月中第几天
System.out.println(cal.get(cal.DAY_OF_MONTH));
//年中第几天
System.out.println(cal.get(cal.DAY_OF_YEAR));
//时间格式化
//年: y ,月: M ,日: d ,时: h/H(小写12制,大写24制) ,分: m ,秒: s ,毫秒:S
//DAteFormat 抽象类
DateFormat df = new SimpleDateFormat("yyyy - MM - dd hh:mm:ss:SS");
DateFormat df1 = new SimpleDateFormat("yyyy - MM - dd HH:mm:ss:SS");
System.out.println(df.format(cal.getTime()));
System.out.println(df1.format(cal.getTime()));
//输出自定义时间,注意每月的天数,多了会往后延续多的日子
cal.set(2021,1,30);
System.out.println(df.format(cal.getTime()));
}
}
LocalDate(年 - 月 - 日)
- Java1.8后新增时间类
- 年月日
public class Study_LocalDate {
public static void main(String[] args) {
//当前年月日
LocalDate ld1 = LocalDate.now();
System.out.println(ld1);
//自定义年月日
LocalDate ld2 = LocalDate.of(2000,07,05);
System.out.println(ld2);
//加减时间
//年
LocalDate ld3 = ld2.plusYears(-5);
//月
ld3 = ld3.plusMonths(+2);
//日
ld3 = ld3.plusDays(+10);
System.out.println(ld3);
//时间格式化
DateTimeFormatter dtf1 = DateTimeFormatter.ISO_LOCAL_DATE;
System.out.println(dtf1.format(ld1));
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
System.out.println(dtf2.format(ld1));
}
}
LocalTime(时: 分 : 秒)
- Java1.8后新增时间类
- 时分秒毫秒
public class Study_LocalTime {
public static void main(String[] args) {
//当前时间
LocalTime lt = LocalTime.now();
System.out.println(lt);
//时间格式化 (H/h) --- (24/12)
DateTimeFormatter dd = DateTimeFormatter.ofPattern("HH:mm:ss");
System.out.println(dd.format(lt));
}
}
LocalDateTime(年 - 月 - 日 时: 分 : 秒)
- Java1.8后新增时间类
- 年月日时分秒毫秒
public class Study_LocalDateTime {
public static void main(String[] args) {
//当前时间
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
//时间格式化 (H/h) --- (24/12)
DateTimeFormatter dd = DateTimeFormatter.ofPattern("yyyy - MM - dd HH:mm:ss");
System.out.println(dd.format(ldt));
}
}
Object类
- 所有类的根父类
public class StudyObject {
public static void main(String[] args) {
Object obj = new Object();
obj = "qwe";
System.out.println(obj.equals("qwe"));
//返回该对象的哈希码,int类型
System.out.println(obj.hashCode());
//输出对象的字符串
System.out.println(obj.toString());
//返回对象字节码对象
System.out.println(obj.getClass());
//void finalize()垃圾回收
}
}
final --- finally --- finalize
- final 可以修饰类,被final修饰的类不能被继承;可以修饰方法,被final修饰的方法不能被重写;可以修饰变量,被final修饰的变量成为常量,必须给初始值,且不能被修改
- finally 一般用于 try -- catch -- finally 中,用于释放资源,因为无论代码是否放生异常,只要不退出程序,那么一定会被执行
- finalize用于垃圾回收机制
String类
- 被final修饰,没有子类
- 字符串中有 length 方法 , 数组中没有 length 方法 ,只有 length 属性
public class StudyString {
public static void main(String[] args) {
//定义
//1、
String s = new String();
s = "abc";
//2、
String str = "abc";
//常用方法
//正则表达
System.out.println("abc".matches("^\\D{3}$"));
//判断相等
System.out.println("abc".equals("abc"));
//替换数据:替换数据,若没有需要被替换的数据,直接输出
System.out.println("abc".replaceAll("ab","12"));
//字符串截取,截掉当前下标之前的内容,返回当前下标以及之后的内容
System.out.println("12345".substring(2));
//截取前闭后开区间的数据
System.out.println("12345".substring(0,3));
//是否以xxx开头
System.out.println("abc".startsWith("ab"));
//是否以xxx结束
System.out.println("abc".endsWith("c"));
//去除两端空格
System.out.println(" abc ".trim());
//将数据转换成字符串
System.out.println("123".valueOf(123456));
//截取字符串,转换为数组
String []s1 = str.split("");
for (String s2 : s1){
System.out.print(s2 + " ");
}
//获取当前索引的值,超过会下标越界
System.out.println("1234".charAt(3));
//返回指定字符串的索引
System.out.println("abcd".indexOf("c"));
//取长度(数组中没有length方法,只有length属性,字符串中有length方法)
System.out.println("123456789".length());
//拼接
System.out.println("abc".concat("12456"));
//转换大写
System.out.println("abc".toUpperCase());
//转换小写
System.out.println("ABC".toLowerCase());
}
}
可变字符串
- StringBuffer --- 可变字符串,节省内存(操作保存在缓存区),jdk1.0后,相对builder慢,线程安全
- StringBuilder --- 可变字符串,节省内存(操作保存在缓存区),jdk1.5后,相对buffer快,线程不安全
- String --- 字符串,操作保存在内存
经常对字符串做修改时,应该转换为可变字符串
public class StudyBuffer {
public static void main(String[] args) {
String str = "abc";
StringBuffer sbf = new StringBuffer(str);
StringBuilder sbd = new StringBuilder(str);
//追加内容
System.out.println("===================追加===================");
sbf.append("123");
sbd.append("123");
System.out.println(sbf.toString());
System.out.println(sbd.toString());
//根据下标添加指定字符串(在该下标后面添加)
System.out.println("===================添加===================");
sbf.insert(2,"oo");
System.out.println(sbf.toString());
sbd.insert(2,"oo");
System.out.println(sbd.toString());
//删除,前闭后开
System.out.println("===================删除===================");
sbf.delete(0,3);
System.out.println(sbf.toString());
sbd.delete(0,3);
System.out.println(sbd.toString());
System.out.println("===================速度===================");
//根据个人电脑情况进行此程序,i值设置过高会导致程序卡死,甚至电脑死机
System.out.println("String速度:");
String s = "a";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 99999; i++){
s+=i;
}
long endTime = System.currentTimeMillis();
System.out.println("循环结束,时间为: " + (endTime - startTime));
//对StringBuffer 和 StringBuilder 进行比较时,最好将String 注释掉,以防卡死
System.out.println("\nStringBuffer速度:");
StringBuffer s2 = new StringBuffer();
startTime = System.currentTimeMillis();
for(int i = 0; i < 99999; i++){
s2.append(i);
}
endTime = System.currentTimeMillis();
System.out.println("循环结束,时间为: " + (endTime - startTime));
System.out.println("\nStringBuilder速度:");
StringBuilder s3 = new StringBuilder();
startTime = System.currentTimeMillis();
for(int i = 0; i < 99999; i++){
s3.append(i);
}
endTime = System.currentTimeMillis();
System.out.println("循环结束,时间为: " + (endTime - startTime));
}
}
运行结果

Math类
- 进行一些数学计算使用
public class StudyMath {
public static void main(String[] args) {
//圆周率
System.out.println(Math.PI);
//自然对数
System.out.println(Math.E);
//绝对值
System.out.println(Math.abs(-15.5));
//四舍五入,不管正负
System.out.println(Math.round(4.7));
System.out.println(Math.round(-7.2));
System.out.println(Math.round(-7.8));
//向上取整,取大的
System.out.println(Math.ceil(4.2));
System.out.println(Math.ceil(4.8));
System.out.println(Math.ceil(-9.2));
System.out.println(Math.ceil(-9.8));
//向下取整
System.out.println(Math.floor(4.2));
System.out.println(Math.floor(4.8));
System.out.println(Math.floor(4.2));
System.out.println(Math.floor(-9.2));
System.out.println(Math.floor(-9.8));
//取最大值
System.out.println(Math.max(3.6,4.7));
//取最小值
System.out.println(Math.min(3.6,4.7));
//开平方
System.out.println(Math.sqrt(4));
}
}
正则表达式
- 一般用来验证格式(手机号、邮箱、身份证号等)
- 正则前为两个 \ ,为了与转义字符区分
- 以 ^ 开始,以 $ 结束
- \d --- 0~9
- \s --- 空格或tab
- \w --- 数字、字母、下划线
- \D --- 除了数字(\d)以外
- \S --- 除了空格、Tab(\s)以外
- \W --- 除了数字、字母、下划线(\w)以外
- '+' --- 至少一位
- ? --- 0位或1位?
- '*' --- 任意位数
- {n} --- n位
- {n,} --- 至少n位
- {n,m} --- n~m位
- [n-m] --- 内容n,m
- [n-m|] --- 内容n,m或
public class StudyReg {
public static void main(String[] args) {
//定义
// \\d --- 0~9
String reg1 = "\\d";
System.out.println("\\d " + " 6 " + "6".matches(reg1));
// \\s --- 空格或tab
String reg2 = "\\s";
System.out.println("\\s " + " [空格] " + " ".matches(reg2));
// \\w --- 数字、字母、下划线
String reg3 = "\\w";
System.out.println("\\w " + " _ " + "_".matches(reg3));
// \\D --- 除了数字(\\d)以外
String reg4 = "\\D";
System.out.println("\\D " + " @ " + "@".matches(reg4));
// \\S --- 除了空格、Tab(\\s)以外
String reg5 = "\\S";
System.out.println("\\S " + " 2 " + "2".matches(reg5));
// \\W --- 除了空格、Tab(\\s)以外
String reg6 = "\\W";
System.out.println("\\W " + " @ " + "@".matches(reg6));
// + 至少一位
String reg7 = "\\d+";
System.out.println("\\d+ " + " 123456 " + "123456".matches(reg7));
// ? 0位或1位?
String reg8 = "\\d?";
System.out.println("\\d? " + " 空 " + "".matches(reg8));
// * 任意位数
String reg9 = "\\d*";
System.out.println("\\d* " + " 123456 " + "123456".matches(reg9));
// {n} n位
String reg10 = "\\d{5}";
System.out.println("\\d{5} " + " 123456 " + "12345".matches(reg10));
// {n,} 至少n位
String reg11 = "\\d{5,}";
System.out.println("\\d{5,} " + " 123456 " + "123456".matches(reg11));
// {n,m} n~m位
String reg12 = "\\d{5,10}";
System.out.println("\\d{5,10} " + " 123456 " + "123456".matches(reg12));
// [n-m] 内容n,m
String reg13 = "[2-6]*";
System.out.println("[2-6]* " + " 236 " + "236".matches(reg13));
// [n-m|] 内容n,m或
String reg14 = "[2-6|a-f|A-F]{3,6}";
System.out.println("[2-6|a-f|A-F]{3,6} " + " 236aB " + "236aB".matches(reg14));
}
}
运行结果

传输流
字节流&字符流
- IO流 计算机的一种用语,用于处理数据的传输
- java一个字符为 2字节 ,一个英文/中文 也是 2字节
- 根据流向可以分为 输入流 、 输出流
- 根据传输格式可分为 字节流 、 字符流
- 根据角色不同可分为 节点流(直接作用于文件) 、 处理流(缓冲流)
- 注意:Windows记事本的换行为 /r/n ,所以换行不能只写 /r 或者 /n
public class StudyOutPlay {
public static void main(String[] args) {
//字节输出流 有参构造,输入目录,在指定目录添加文件,书写文件
try {
File file1 = new File("D:/LQDYY/学/中软/test.txt");
//文件未找到情况需要catch抓包解决问题
FileOutputStream fos = new FileOutputStream(file1);
//字节流无法输出中文,会乱码,需要使用字符流输出中文
String str1 = "hello world";
for(int i = 0; i< str1.length(); i++){
//注意IO流异常,需要catch抓包解决问题
fos.write(str1.charAt(i));
}
System.out.println("已创建");
//确保关闭文件
fos.flush();
fos.close();
}catch (FileNotFoundException e){
System.out.println("文件未找到!");
}catch (IOException e){
System.out.println("IO流异常");
}
//字节输入流
try {
File file2 = new File("D:/LQDYY/学/中软/test.txt");
//文件未找到情况需要catch抓包解决问题
FileInputStream fis = new FileInputStream(file2);
//file.length()文件内容长度,字节流以字节输入
byte []b = new byte[(int)file2.length()];
//注意IO流异常,需要catch抓包解决问题
fis.read(b);
String str2 = new String(b);
System.out.println(str2);
fis.close();
}catch (FileNotFoundException e){
System.out.println("文件未找到!");
}catch (IOException e){
System.out.println("IO流异常");
}
//字符输出流
try {
File file3 = new File("D:/LQDYY/学/中软/test.txt");
//文件未找到情况需要catch抓包解决问题
FileWriter fw = new FileWriter(file3);
String str3 = "你好";
//注意IO流异常,需要catch抓包解决问题
fw.write(str3);
System.out.println("已创建");
fw.flush();
fw.close();
}catch (FileNotFoundException e){
System.out.println("文件未找到!");
}catch (Exception e){
System.out.println("IO流异常");
}
//字符输入流
try {
File file4 = new File("D:/LQDYY/学/中软/test.txt");
//文件未找到情况需要catch抓包解决问题
FileReader fr = new FileReader(file4);
char []c = new char[(int)file4.length()];
//注意IO流异常,需要catch抓包解决问题
fr.read(c);
String str4 = new String(c);
System.out.println(str4);
fr.close();
}catch (FileNotFoundException e){
System.out.println("文件未找到!");
}catch (Exception e){
System.out.println("IO流异常");
}
}
}
BufferWriter && BufferReader
- 处理输出流,处理输入流
public class StudyBufferWriter {
public static void main(String[] args) {
//输出处理流
try {
File file = new File("D:\\LQDYY\\学\\中软\\test.txt");
//文件未找到情况需要catch抓包解决问题
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
String str = "辽宁科技大学";
bw.write(str);
System.out.println("已创建");
bw.flush();
bw.close();
}catch (IOException e){
System.out.println("IO流异常");
}
//输入处理流
try {
File file2 = new File("D:\\LQDYY\\学\\中软\\test.txt");
//文件未找到情况需要catch抓包解决问题
FileReader fr = new FileReader(file2);
BufferedReader br = new BufferedReader(fr);
String s = null;
//注意IO流异常,需要catch抓包解决问题
while ((s = br.readLine()) != null)
System.out.println(s);
br.close();
}catch (FileNotFoundException e){
System.out.println("文件未找到!");
}catch (Exception e){
System.out.println("异常");
}
}
}
总结

可变参数
- public void f(Int...a)
- 可变参数,jdk1.5
- 可以存储null
- 可以存储数组
- 可变参数需要放在形参后
- 可变参数可以被重载,当执行一个或多个参时,优先执行明确参数个数的方法,只有当参数数量在重载方法中没有时,才会执行可变参数
- 当定义的类型为包装类时,不要给null值,防止多个可变参数的方法都适用,编译出错
- 类中不能定义和可变参数同类型的数组,可变参数可以传递数组,兼容数组,但形参维数组不能传递可变参数的数据,不兼容可变参数
public class Dongtai {
public static void DTf(Object...obj){
System.out.print("可变参数: ");
for(Object o : obj){
System.out.print(o + " ");
}
System.out.println();
}
public static void DTf(String a,int b){
System.out.print("重载: ");
System.out.println(a);
}
public static void DTf1(String a, Object...obj){
System.out.print("可变参数2: ");
System.out.print(a + " ");
for(Object o : obj){
System.out.print(o + " ");
}
}
public static void main(String[] args) {
Object []obj1 = {1,2,3,4,5,6,7,8,9};
DTf(obj1);
DTf("abc",123,"def");
DTf("abc",123);
DTf1("123",obj1);
}
}
运行结果

注意给予模糊参数问题
- 包装类默认值为null,String类型默认值也是null,此时无法执行
public static void DTf(String a,int b){
System.out.print("重载1: ");
System.out.println(a);
}
public static void DTf(Integer a,int b){
System.out.print("重载2: ");
System.out.println(a);
}
public static void main(String[] args) {
//机器无法确认需要执行哪个方法
Dtf(null,123)
}
多线程
多线程 --- Thread 类 实现
- Thread类,只能开启多个同一线程,无法开启多个不同的线程(类只能单一继承)
- Thread 是 Runnable接口的实现类
- 声明类时需要继承Thread类
- 需要重写run方法
- 主方法 在多线程中叫 主线程
- run()方法为调用线程,start()为开启线程
- 多线程由CPU进行调度
public class Study_Thread extends Thread{
@Override
public void run(){
for (int i = 1; i <= 5; i++){
System.out.println("上课第 " + i + " 天");
}
/*for (int i = 1; i <= 5; i++){
System.out.println(Thread.currentThread().getName() + "上课第 " + i + " 天");
}*/
}
public static void main(String[] args) {
Study_Thread t = new Study_Thread();
t.start();
for (int i = 1; i <= 5; i++){
System.out.println("玩手机 " + i + " 天");
}
/*new Thread(t,"f1").start();
new Thread(t,"f2").start();
new Thread(t,"f3").start();*/
}
}
运行结果


多线程 --- Runnable 接口 实现
- Runnable接口,可以开启多个不同的线程,也可以开启多个相同的线程(接口可以多继承)
- implements 实现接口 Runnable
- 重写 run 方法
public class Study_Runnable implements Runnable{
@Override
public void run(){
for (int i = 1; i <= 5; i++){
System.out.println(Thread.currentThread().getName() + "上课第 " + i + " 天");
}
}
public static void main(String[] args) {
Study_Runnable r = new Study_Runnable();
/*//代理模式
Thread t = new Thread(r);
t.start();*/
//多线程
new Thread(r,"甲").start();
new Thread(r,"乙").start();
new Thread(r,"丙").start();
}
}
运行结果

线程操作
线程同步
- 毫不干预情况下多个线程对同一变量进行操作时容易发生线程不安全情况
public class Ticket implements Runnable{
int ticket = 10;
@Override
public void run(){
while(true){
System.out.println(Thread.currentThread().getName() + " " + (ticket--));
if(ticket <= 0)
break;
}
}
public static void main(String[] args) {
Ticket t = new Ticket();
//线程不安全
new Thread(t,"张三").start();
new Thread(t,"李四").start();
new Thread(t,"王五").start();
}
}
- 优点:解决线程不安全
- 缺点:速度慢
public class Ticket implements Runnable{
int ticket = 10;
boolean flag = true;
@Override
public void run(){
while(flag){
buy();
}
}
//同步
public synchronized void buy(){
if (ticket <= 0){
flag = false;
}else{
System.out.println(Thread.currentThread().getName() + " " + (ticket--));
}
}
public static void main(String[] args) {
Ticket t = new Ticket();
new Thread(t,"张三").start();
new Thread(t,"李四").start();
new Thread(t,"王五").start();
}
}
线程停止
- 标志位 --- 用来停止线程 --- 现已不使用线程自带的停止方法(过时)
boolean flag = true;
public void stop(){
flag = false;
}
public static void main(String[] args) {
t.stop();
}
线程休眠
- Thread . sleep (毫秒)
public class Study_Sleep implements Runnable{
int i = 0;
@Override
public void run(){
try{
while(true){
//long类型,毫秒
Thread.sleep(1000);
System.out.println(i++);
if(i == 10)
break;
}
}catch (InterruptedException e){
System.out.println("线程阻塞异常");
}
}
public static void main(String[] args) {
Study_Sleep s = new Study_Sleep();
new Thread(s).start();
}
}
线程礼让
- 礼让不一定成功,取决于CPU
public class Study_Yield implements Runnable{
@Override
public void run () {
System.out.println(Thread.currentThread().getName());
//线程礼让
Thread.yield();
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
Study_Yield y = new Study_Yield();
///礼让成功:甲乙乙甲 、 乙甲甲乙 ;礼让失败:甲乙甲乙、乙甲乙甲、乙乙甲甲 ; 非多线程:甲甲乙乙
new Thread(y,"甲").start();
new Thread(y,"乙").start();
}
}
线程抢占
- 抢占一定会成功
- 抢占会出现异常,需要用 try ... catch 环绕
- 抢占前线程完成,不会进行抢占
ublic class Study_Join implements Runnable{
@Override
public void run () {
for(int i = 0; i <= 100; i++){
System.out.println("线程 " + i);
}
}
public static void main(String[] args) {
Study_Join j = new Study_Join();
Thread t = new Thread(j);
t.start();
for (int i = 0; i <= 50; i++){
System.out.println("主线程 " + i);
if(i == 10){
try {
//抢占
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
守护线程
- 守护者虽然是无限循环,但是因为作为守护者,被守护者执行完成守护者也结束
/*==============守护者==============*/
public class Angel implements Runnable{
@Override
public void run(){
int i = 0;
while(true){
System.out.println("守护者 " + i++);
}
}
}
/*==============被守护==============*/
public class Pe_user implements Runnable{
@Override
public void run(){
for(int i = 0; i < 100; i++){
System.out.println("被守护 " + i);
}
}
}
/*==============测试类==============*/
public class Test {
public static void main(String[] args) {
Angel a = new Angel();
Pe_user p = new Pe_user();
Thread t = new Thread(a);
//开启守护线程
t.setDaemon(true);
t.start();
//开启被守护的线程
new Thread(p).start();
}
}
线程优先级
- 优先级1 - 10
- 数字越大等级越高
- 优先级执行是不一定的,取决于CPU
- 性能倒置:没有按照多线程优先级执行
- 使用优先级只能加大概率,不能完全决定线程的先后
public class Study_First implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+ " " +Thread.currentThread().getPriority());
}
public static void main(String[] args) {
Study_First f = new Study_First();
//十级
Thread t = new Thread(f,"甲");
t.setPriority(Thread.MAX_PRIORITY);
t.start();
//五级
t = new Thread(f,"乙");
t.setPriority(Thread.NORM_PRIORITY);
t.start();
//一级
t = new Thread(f,"丙");
t.setPriority(Thread.MIN_PRIORITY);
t.start();
//自定义级
t = new Thread(f,"丁");
t.setPriority(3);
t.start();
}
}
Lambda 表达式
- 函数接口(function interface)
- 去掉多余代码,留下精简部分
- 防止匿名内部类冲突
- 条件: 一个接口中只有一个抽象类
无参 Lambda
- 表达式:对象名 = ()->内容 ;
public interface Study_Lam {
public void show();
}
public class LamT{
public static void main(String[] args) {
Study_Lam l = new Study_Lam() {
@Override
public void show() {
System.out.println("show1");
}
};
l.show();
l = ()->{
System.out.println("show2");
};
l.show();
l = ()-> System.out.println("show3");
l.show();
}
}
有参 Lambda
- 表达式:对象名 = (参数)->内容 ;
/*===========接口============*/
public interface Study_Lam {
public void show(String str);
}
/*===========实现类============*/
public class Lam_Do implements Study_Lam{
@Override
public void show(String str){
System.out.println(str + " show1");
}
}
/*===========测试类============*/
public class LamT{
public static void main(String[] args) {
Study_Lam l = new Lam_Do();
l.show("张三");
l = (String str)->{
System.out.println(str + " show2");
};
l.show("李四");
l = (str)->{
System.out.println(str + " show3");
};
l.show("王五");
l = (String str)-> System.out.println(str + " show4");
l.show("小六");
l = (str)-> System.out.println(str + " show5");
l.show("吴七");
}
}
内存
堆
- 堆:引用类型 --- new的内容存储在堆中,当内容运行完毕后会通过垃圾回收机制自动回收
栈
- 栈:基本数据类型 --- 处理速度快
堆栈转换
- 当 基本数据类型 和 包装类 进行比较时,值相同,结果为 true
- 当 包装类 与 另一同类型包装类 在都没有 new 的情况下 且没有超过非自动装箱范围,结果为 true
- 当 包装类 与 另一同类型包装类 在某一方 new 、双方都 new 的情况下,结果为 false
- 当 包装类 与 另一同类型包装类 在都没有 new 的情况下 但超过非自动装箱范围,结果为 false
public class Study_NeiCun {
public static void main(String[] args) {
System.out.println("\n=======int======\n");
int a = 10;
int b = 10;
Integer c = 10;
Integer d = new Integer(10);
int e = 1000;
Integer f = 1000;
Integer g = new Integer(1000);
System.out.println("=====10=====");
System.out.println(a == b); // true
System.out.println(a == c); // true
System.out.println(a == d); // true
System.out.println(c == d); // false
System.out.println("\n====1000====");
System.out.println(e == f); // true
System.out.println(e == g); // true
System.out.println(f == g); // false
System.out.println("\n=====String=====\n");
String str1 = "java";
String str2 = "java";
String str3 = new String("java");
String str4 = new String("java");
System.out.println("java" == str1); // true
System.out.println("java" == str3); // false
System.out.println(str1 == str2); // true
System.out.println(str2 == str3); // false
System.out.println(str3 == str4); // false
System.out.println("\n=======数组=======\n");
int []arr1 = new int[4];
int []arr2 = new int[4];
int []arr3 = {1,2,3,4};
int []arr4 = {1,2,3,4};
System.out.println(arr1 == arr2); //false
System.out.println(arr3 == arr4); //false
}
}