导图社区 java基础
java基础知识总结,详细介绍Java各种基础知识,相信你会收获颇丰。后期会继续扩展更多知识,敬请期待。
编辑于2022-01-06 17:25:17Java基础
基础程序设计
搭建Java的开发环境
安装JDK和配置环境变量
第一个Java程序
Java程序的编译与运行过程
关键字和保留字,标识符
命名规则
•定义合法标识符规则: >由26个英文子母大小写,0-9或$组成 >数字不可以开头。 >不可以使用关键字和保留字,但能包含关键字和保留字。 >Java中严格区分大小写,长度无限制。 >标识符不能包含空格。 不遵守编译不通过
命名的规范
•Java中的名称命名规范: >包名:多单词組成时所有字母都小写:xxxyyyzzz >类名、接口名:多单词組成时,所有单词的首字母大写:XxxYyyZzz >变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每单词首字母大写:xxxYyyZzz >常量名:所有字母都大写。多单词时每个单词用下划线连接:xXX_YYY_ZZz •注意1,在起名时,为了提高阅读性,要尽量有意义,“见名知意” 建议,不遵守编译也可以通过
变量
基本数据类型
基本数据类型
整型:byte1\short2\int4\long8 浮点型:float4\double8 字符型:char2 布尔型:boolean1 byte1字节-8位, short2-16, int 4-32 , long 8-64, float 4-32, double 8-64, chart 2-16, boolean 1-8 class VariableTest3 { public static void main(String[] args) { byte b1=2; int i1=129; //编译不通过 //byte b2=b1+i1; int i2=b1+i1; System.out.println(i2); float f=b1+i1; System.out.println(f); short s1=123; double d1=s1; System.out.println(d1); //******************************* char c1='a'; int i3=10; int i4=c1+i3; System.out.println(i4); short s2=10; //char c2=c1+s2;//编译不通过 byte b2=10; //char c3=c1+b2;//编译不通过 //short s3=b2+s2;//编译不通过 //short s4=b1+b2;//编译不通过
引用数据类型
类class 接口interface 数组array
基本数据类型变量之间转换
byte、char、short-->int--> long--> float-- >double 关于强制类型转换 强制类型转换:自动类型提升的逆运算。 1、需要使用强转符:() byte、char、short-->int--> long--> float-- >double 往这个反方向进行转换就需要强转(容量大转换成容量小的) 2、注意点:强制类型转换可能导致精度损失。 ********* //精度损失举例1 double d1=12.3; int i1=(int)d1; //截断操作 System.out.println(i1); //没有精度损失 long l1=123; short s2=(short)l1; //精度损失举例2 int i2=128; byte b=(byte)i2; System.out.println(b);//-128
基本数据类型与String间转换
/* String类型变量的使用 1.String数据引用数据类型,翻译为:字符串 2.声明String类型变量时,‘使用一对’ 3.String可以和8种基本数据类型变量做运算,且运算只能是连接运算:+ 4.运算的结果是String类型 */ class StringTest { public static void main(String[] args) { String s1="Hello,World!"; System.out.println(s1); String s2="a"; String s3=""; //char c='';//编译不通过 //********************** int number=1001; String numberStr="学号:"; String info=numberStr+number;//+:连接运算 System.out.println(info); boolean b1=true; String info1=info+b1;//+连接运算 System.out.println(info1); //********************** //练习1 char c='a';//a=97 A=65 int num=10; String str="hello"; System.out.println(c+num+str);//107hello System.out.println(c+str+num);//ahello10 System.out.println(c+(num+str));//a10hello System.out.println((c+num)+str);//107hello System.out.println(str+num+c);//hello10a //********************** //练习2 //输出:* * System.out.println("* *"); System.out.println('*'+'\t'+'*'); System.out.println('*'+"\t"+'*'); System.out.println('*'+'\t'+"*"); System.out.println('*'+('\t'+"*")); //********************** //String str1=123;//编译不通过 String str1=123+""; System.out.println(str1);//"123" //int num1=str1; //int num1=(int)str1;//"123" int num1=Integer.parseInt(str1); System.out.println(num1);//123 } }
进制与进制间的转换

运算符
运算行是一种特殊的行号,用以表示数据的运第、赋值和比较等。
算数运算符
 class AriTest{ public static void main(String[] args) { //除号:/ int num1=12; int num2=5; int result1=num1/num2; System.out.println(result1);//2 int result2=num1/num2*num2; System.out.println(result2);//10 double result3=num1/num2; System.out.println(result3);//2.0 double result4=num1/num2+0.0;//2.0 double result5=num1/(num2+0.0);//2.4 double result6=(double)num1/num2;//2.4 System.out.println(result5); System.out.println(result6); //%:取余运算 //结果的符号与被模数的符号相同 //开发中,经常使用%来判断是否能除尽的情况 int m1=12; int n1=5; System.out.println("m1 % n1=" + m1 % n1); int m2=-12; int n2=5; System.out.println("m2 % n2=" + m2 % n2); int m3=12; int n3=-5; System.out.println("m3 % n3=" + m3 % n3); int m4=-12; int n4=-5; System.out.println("m4 % n4=" + m4 % n4); //(前)++:先自增1,然后再运算 //(后)++ :先运算,后自增1 int a1=10; int b1=++a1; System.out.println("a1="+a1 + ",b1=" + b1); int a2=10; int b2=a2++; System.out.println("a2="+a2 + ",b2=" + b2); int a3=10; a3++;//只涉及自增1,不涉及别的运算(无论前++还是后++) int b3=a3; //注意点: short s1=10; //s1=s1+1;//编译失败,涉及+1为整型,int转short× s1=(short)(s1+1);//(编译成功) s1++;//自增1不会改变本身变量的数据类型 System.out.println(s1); //问题 byte bb1=127; b1++; System.out.println("bb1="+bb1); //(前)--:先自减1,后运算 //(后)--:先运算,后自减1 int a4=10; int b4=--a4; System.out.println("a4="+a4 + ",b4="+b4);//99 int a5=10; int b5=a5--; System.out.println("a5="+a5 + ",b5="+b5);//9,b5=10 } }
赋值运算符
运算符之二:赋值运算符 = += -+ *= /= %= class SetValueTest { public static void main(String[] args) { //赋值符号:= int i1=10; int j1=10; int i2,j2; //连续赋值 i2=j2=10; int i3=10,j3=20; //******************* int num1 = 10; num1 += 2;//num1=num1+2; System.out.println(num1);//12 int num2=12; num2 %=5;//num2%5; System.out.println(num2);//2 short s1=10; //s1=s1+2;//编译失败,需要用int接收或则强转成short s1+=2;//不会改变本身的数据类型 System.out.println(s1); //开发中,如果希望变量实现+2的操作,有几种方法?(前提:int num=10;) //方式一:num=num+2; //方式二:num+=2;(推荐) //开发中,如果希望变量实现+2的操作,有几种方法?(前提:int num=10;) //方式一:num=num+1; //方式二:num+=1; //方式三:num++;(推荐) //练习1 int i=1; i*=0.1; System.out.println(i);//0 i++; System.out.println(i);//1 //练习2 int m=2; int n=3; n*=m++;//n=n*m++;//(后++,先运算N=6,在加1得M=3) System.out.println("m="+m);//3 System.out.println("n="+n);//6 //练习3 int n1=10; n1+=(n1++)+(++n1);//n1=n1+(n1++)+(++n1); System.out.println(n1);//32 } }
比较运算符
 class CompareTest { public static void main(String[] args) { int i=10; int j=20; System.out.println(i==j);//false System.out.println(i=j);//20,先将j赋值给i,再输出i boolean b1=true; boolean b2=false; System.out.println(b1==b2);//false System.out.println(b2=b1);//true } }
逻辑运算符
实记 /* 运算符之四:逻辑运算符 说明: 逻辑运算符操作的都是boolean类型的变量 */ class LogicTest { public static void main(String[] args) { //区分&与&& //相同点1:&与&&的运算结果相同 //相同点2:但符号左边是true,二者都会执行符号右边的运算 //不同点:当符号左边是false时,&继续执行符号右边的运算,&&不再执行符号右边的运算 //开发中推荐使用&& boolean b1=true; b1=false; int num1=10; if(b1&(num1++>0)){ System.out.println("我现在在北京"); }else{ System.out.println("我现在在南京"); } System.out.println("num1="+num1); boolean b2=true; b2=false; int num2=10; if(b2&&(num2++>0)){ System.out.println("我现在在北京"); }else{ System.out.println("我现在在南京"); } System.out.println("num2="+num2); //区分:|与|| //相同点1:|与||的运算结果相同 //相同点2:但符号左边是false,二者都会执行符号右边的运算 //不同点:当符号左边是true时,|继续执行符号右边的运算,||不再执行符号右边的运 开发中推荐使用|| boolean b3=false; b3=true; int num3=10; if(b3|(num3++>0)){ System.out.println("我现在在北京"); }else{ System.out.println("我现在在南京"); } System.out.println(" num3 = " + num3); boolean b4=false; b4=true; int num4=10; if(b4||(num4++>0)){ System.out.println("我现在在北京"); }else{ System.out.println("我现在在南京"); } System.out.println(" num4 = " + num4); } } 
三元运算符
 /* 运算符之六:三元运算符 1,结构:(条件表达式)?表达式1:表达式二 2.说明 ①条件表达式的结果为boolean类型 ②根据据条件表达式的真或则假,决定执行表达式1,还是表达式2 如果表达式为true则执行表达式1 如果表达式false则执行表达式2 ③表达式1和表达式2的要求(数据类型)的是一致的,能够统一为一个类型也可。 ④三元运算符是可以嵌套使用的 3.凡是可以使用三元运算符的地方,都可改写成if,else。 能用if-else的地方不一定能够改成三元 4.如果程序可以使用三元运算符,又就可以使用if,else结构 优先选择三元运算符,原因:简介,执行效率高。 */ class SanYuanTest { public static void main(String[] args) { //获取两个整数的较大值 int m=12; int n=5; int max=(m>n)?m:n; System.out.println(max); double num=(m>n)?2:1.0; //统一为一个类型 //(m>n)?2:"n大";//编译错误 //*************************** String maxStr=(m>n)?"m大":((m==n)?"m和n相等":"n大"); System.out.println(maxStr); //*************************** //获取三个数的最大值 int n1=12; int n2=30; int n3=-43; int max1=(n1>n2)?n1:n2; int max2=(max1>n3)?max1:n3; System.out.println("三个数中的最大值为:"+max2); //改写成if-else if(m>n){ System.out.println(m); }else{ System.out.println(n); } } }
位运算符
   /* 运算符之五:位运算符(了解即可) 结论: 1位运算符操作的都是整型的数据 2<<在一定范围内,每向左移一位,相当于*2 >>在一定范围内,每向右移一位,相当于/2 面试题:最高效的方式计算2*8? 2<<3或则8<<1 */ class BitTest { public static void main(String[] args) { int i=21; System.out.println("i<<2:"+(i<<2));//21*4 System.out.println("i<<3:"+(i<<3));//21*8//每项左移一位乘2 int m=12; int n=5; System.out.println("m&n:"+(m&n));//m&n:4 System.out.println("m|n:"+(m|n));//m|n:13 System.out.println("m^n:"+(m^n));//m^n:9 } } 
流程控制
顺序结构 分支结构 循环结构 ①初始化部分 ②循环条件部分 ③循环体部分 ④迭代部分 /*
如何重控制台获取不同的变量Scanner
/* 如何重控制台获取不同类型的变量:需要使用scanner类 一、具体实现步骤 形式1 1.导包 import java.until.Scanner; 2.scanner的实例化 Scanner scan=new Scanner(System.in); 3.调用scanner类的相关方法next()/nextXxx,来获取指定类型的变量 形式2 1、准备Scanner类型的变量 java.util.Scanner input = new java.util.Scanner(System.in); Scanner input=new Scanner(System.in); 2、提示输入xx System.out.print("请输入一个整数:"); 3、接收输入内容 int num = input.nextInt(); long bigNum = input.nextLong(); double d = input.nextDouble(); boolean b = input.nextBoolean(); String s = input.next(); char c = input.next().charAt(0);//先按照字符串接收,然后再取字符串的第一个字符(下标为0) 注意: 需要根据相应的方法来输入指定的值,如果输入的数据类型与要求的类型不匹配时,我们会报异常:InputMismatchExceptiond导致程序终止 。 */ import java.util.Scanner;//util避免为until public class ScannerTest { public static void main(String[] args) { //Scanner scan=new Scanner(System.in); //int num=scan.nextInt(); //System.out.println(num); //*********************** Scanner scan=new Scanner(System.in); System.out.println("请输入你的姓名"); String name=scan.next();//scan.next接收为字符串 System.out.println(name); System.out.println("请输入你的年龄"); int age=scan.nextInt(); System.out.println(age); System.out.println("请输入你的体重"); double weight=scan.nextDouble(); System.out.println(weight); System.out.println("你是否相中我了呢?(true/false)");//注意双引号的位置 boolean isLove=scan.nextBoolean(); System.out.println(isLove); //对于char型的获取,scanner没有提供祥光的方法,只能获取一个字符串。 System.out.println("请输入你的性别:(男/女)"); String gender=scan.next();//"男" char genderChar=gender.charAt(0);//获取索引为0位置上的字符 } } 练习 import java.util.Scanner; //S大写 public class IfTest{ public static void main(String[] args) { Scanner scan=new Scanner(System.in); System.out.println("请输入越小彭成绩:(0-100)"); int score=scan.nextInt(); if(score==100){ System.out.println("奖励一台宝马车"); }else if(score>80&&score<=99){ System.out.println("奖励一台手机"); }else if(score>=60&&score<=80){//颠倒else和elseif的结构不会发生变化 System.out.println("奖励一台ipad"); }else{ System.out.println("啥奖励也没有");蓝色部分可以注释掉,else结构是可选的 } } }  1针对条件表达式,如果多个条件表达式之间是“互斥或则互不包含关系”,那个判断和执行语句在声明上面无所谓 2.如果多个条件之间有交集关系,例如上图表达错误,应该根据实际情况考虑清楚那个结构在上面 3如果是1包含2,通常情况下需要将范围小的声明在范围大的上面,否则小的就没有机会执行
switch-case结构
基本结构:case后只能有一个常量 switch(表达式){ case 常量值1: 语句块1; 【break;】 case 常量值2: 语句块2; 【break;】 。。。 【default: 语句块n+1; 【break;】 】 ①Switch结构的表达式中,只能是如下6中数据类型:byte.short.char, int ,枚举类型,String类型。 ②case 之后不能定义范围。 ③switch关键字后面小括号有一个变量,用这个变量和case后面的常量值进行匹配 //编译失败 //编译失败 public class SwitchCaseTest { public static void main(String[] args) { int number =2; switch(number){ case 0: System.out.println("zero"); break; case 1: System.out.println("one"); break; case 2: System.out.println("two"); break; case 3: System.out.println("three"); break; case 4: System.out.println("other");//two,three,other(在结尾出没有加Breaks时) } } } 举例2 
if-else结构
 /* 三种结构 1、 if(条件表达式){ 语句体; } 2、 if(关系表达式) { 语句体1; }else { 语句体2; } 3、 if (判断条件1) { 执行语句1; } else if (判断条件2) { 执行语句2; } ... }else if (判断条件n) { 执行语句n; } else { 执行语句n+1; } */ public class IfTest { public static void main(String[] args) { //举例1 int heartBeats=79; if(heartBeats<60||heartBeats>100);{ System.out.println("需要进一步检查"); } System.out.println("检查结束"); //举例2 int age=23; if(age<18){ System.out.println("你还可以看动画片"); }else{ System.out.println("你可以看电影了"); } //举例3 1、多重if-else结构必须以以IF开头,但是IF只能有一个 2、从第一个条件自上而下判断每一个条件 3、当上一个条件位True时,执行代码块,退出整个结构 4、当条件判断位false,则向下判断下一个条件 if (age<0){ System.out.println("您输入的数据非法"); }else if(age<18){//else if可以有任意多个 System.out.println("青少年时期"); }else if(age<35){ System.out.println("青壮年时期"); }else if(age<60){ System.out.println("中年时期"); }else if(age<120 ){ System.out.println("老年时期"); }else{ System.out.println("你是要成仙"); } } }
for结构
For循环结构的使用 一、循环结构的四要素 ①初始化部分(可以声明多个循环变量) ②循环条件部分-------> Boolean类型 ③循环体部分 ④迭代部分 二,for循环的结构 循环次数确定的循环 for(①;②;④){ ③ } 执行过程①--②(满足之后)--③----④---②--③---④...--② */ public class ForTest { public static void main(String[] args) { for(int i=1;i<=5;i++){//i:1,2,3,4,5 System.out.println("Hello,World!"); } } }
练习题
/* 编写程序从1循环到150,并且在每行打印一个值 另外在每个3的倍数行上打印出“foo" 在每个5的倍数行上打印出“biz” 在每个7的倍数行上打印出“baz” */ public class ForTest1 { public static void main(String[] args) { for(int i=1;i<=150;i++){ System.out.print(i +" "); if(i % 3 == 0){ System.out.print("foo"); } if(i % 5 == 0){ System.out.print("biz"); } if(i % 7 == 0){ System.out.print("baz"); //换行 System.out.println(i); } //不能漏掉} } } }
while循环使用
/* While循环的使用 while循环先判断后执行的循环 要求:循环变量必须满足初始循环条件 一、循环结构的4要素 ①初始化部分 ②循环条件部分 ③循环体部分 ④迭代部分 二、循环结构 ① While(②){ ③; ④; } 说明; 1、写While循环千万不要丢了迭代条件,如果丢了就会进行死循环。 2、我们写程序要避免出现死循环 3、for循环和While循环是可以进行相互转换的 算法:有限性 区别;for循环和while循环的初始化条件部分的作用的范围不同 执行过程1-2-3-4-2-3-4-----2 */ public class WhileTest { public static void main(String[] args) { //遍历100以内的所有偶数 int i=1; while(i<=100){ if(i % 2 == 0){ System.out.println(i); } i++;//改变循环变量,不满足条件后退出循环,否则一直满足条件进入死循环 } //i是定义在外面的,出了循环后任然可以进行运算 System.out.println(i);//当while后的条件不满足时跳出循环输出 } } public class TestEight { public static void main(String[] args) { int i=1; int sum=0; while(i<=100){ sum+=i; i++; } System.out.println(sum); } } 题:遍历100-999中的所有水仙花数 搭建循环框架 题:  循环结构选错,有重复部分。 应该使用以下结构do-while  利用Boolean来控制循环
do-while
/* do-while结构的的循环使用 一、循环结构的4要素 ①初始化部分 ②循环条件部分 ③循环体部分 ④迭代部分 二、循环结构 ① do{ ③; ④; }while(②); 执行过程:1-3-4-2-3-4---..--2 说明: 1.do-while循环至少会执行一次循环体! 2.先执行一次循环操作再判断条件,条件为true则继续执行do 3.do-while适合处理循环条件依赖循环操作的情况 */ public class DOWhileTest { public static void main(String[] args) { //遍历100以内的偶数,并且计算所有偶数的和,和个数。 int num=1; int sum=0;//记录总和 int count=0;//记录个数 初始化部分 do{ if(num % 2== 0){//在小括号后面部分没有分号 System.out.println(num); sum += num; count++; 循环体 } num++;迭代部分 }while(num<=100);//条件部分 System.out.println("总和个数为"+sum); System.out.println("个数为"+count); } }  练习;键盘输入密码和确认密码,两次密码一致则退出循环打印注册成功 两次密码不一致则继续输入,直到两次密码一致。 分析→ import java.util.Scanner; public class TestO2 { public static void main(String[] args) { Scanner input = new Scanner(System.in); String password1;//不赋值也可以编译,因为do-while至少循环一次 String password2; //boolean flag;//用来控制循环 do{ //flag = false; System.out.println("请输入密码"); password1 = input.next(); System.out.println("请确认密码"); password2 = input.next(); if(!password1.equals(password2)){//字符串全等于.equals System.out.println("两次密码不一致,重新输入"); } }while(!password1.equals(password2)); System.out.println("注册成功");//!英文条件下 } }
嵌套循环使用
/* 嵌套循环的使用 1.嵌套循环:将一个循环结构A声明在另外一个循环结构B中,就构成一个嵌套循环 2. 外层循环:循环结构B 内层循环:循环结构A 3说明 ①内层循环遍历一遍,只相当于外层循环循环体执行了一次 ②假设外层循环需要执行M次,内层循环执行N次,此时内层循环的循环体一共执行了M*N次 4技巧 外层控制行数,内层控制列数 */ public class ForForTest { public static void main(String[] args) { //****** for(int i =1; i<=6; i++){ System.out.print('*'); } System.out.println("\n"); /*输出 ******* ******* ******* ******* */ for(int j=1;j<=4;j++){ for(int i =1; i<=6; i++){ System.out.print('*'); } System.out.println();//内层循环4次才进行一次外层循环 } /* * ** *** **** ***** */ for(int i=1;i<=5;i++){//外层循环控制行数 for(int j =1;j<=i;j++){//i随着j的改变而改变,j控制列数 System.out.print("*");//当j=1执行循环,叠加后J=1为2,跳出循环进行换行操作 } System.out.println(); } } }  for(int j =5;j >= i;j--){ //J-- 练习3   练习4、3个班级,每个班级4个学生计算平均分  嵌套循环的应用  public class Test11 { public static void main(String[] args) { for(int i = 1;i <=9;i++){ for(int j = 1;j <= i;j++){ System.out.print(i+"*"+j+"="+(i*j)+"\t "); } System.out.println(""); } }}
break和continue
特殊关键字的使用 /* break和continue关键字的使用 使用范围 循环中使用的作用 break: switch-case 结束当前循环 循环结构中 continue: 循环结构中 结束当次循环 二者的相同点:关键字后面不能有执行语句,不能声明语句。 */ public class BreakContinueTest{ public static void main(String[] args) { for(int i=1;i<=10;i++){ if(i%4==0){ //break;//123 continue;//123567910 } System.out.println(i); } } } //*********************** label:for(int i=1;i<=4;i++){ for(int j=1;j<=10;j++){ if(j%4==0){ //break;//默认跳出包裹次关键字的最近的一层循环 //输出4行123 //continue;//输出4行1235678910 //break label;//结束指定标识一层的循环结构//123 continue label;//结束指定标识de一层的循环结构的当此的循环:123123123123 } System.out.print(j); } System.out.println(); } } }
项目二
Customer类的设计
Customer为实体类,用来封装客户信息 该类封装客户的以下信息: String name :客户姓名 String gender :性别 int age :年龄 String phone:电话号码 String email :电子邮箱 提供各属性的get/set方法 提供所需的构造器 (可自行确定) @Override public String toString() { return custName+"\t"+custGender+"\t"+custAge+"\t"+custPhone+"\t"+custEmail; }
CustomerView设计
1.设计展示主菜单方法 2.由此产生输入对应数值选择需要的操作去跳转到相应的作用位置 利用do-while和switch-case结构匹配对应方法和操作 3.设计CustomerList 4.创建CustomerList对象,作为该类的属性 5添加用户 创建对象Customer 打印输入信息 输入辅助 利用list.调用addCustomer方法 打印添加用户成功 展示列表 6更新信息 输入需要更新的用户名字 打印输入,定义String name接收 Customer customer = customerList.getCustomerByName(name); 如果不为空值 Customer newCustomer = new Customer(); 进行输入赋值更新 否则打印未指定姓名的用户,更新失败 7删除信息 输入需要删除的用户名字 打印输入,定义String name接收 Customer customer = customerList.getCustomerByName(name);这个位置指的是通过姓名去数组当中匹配我要删除的信息,创建一个对象去接收我找到的东西 如果不为空值直接调用方法删除 否则打印未找到指定名称的用户
CustomerList设计
1.创建数组装载客户信息,设置属性int total记录当前数 private Customer[] customers;// 装载客户信息的数组 private int total;// 当前保存的客户数 2.创建构造器,无参和有参,有参给定initCount作为形参 重写构造器 Customer customer1 = new Customer()//做测试用 customers[0] = customer1;//做测试用 3.设计 public void addCustomer(Customer customer){}方法 思路: 定义索引,给定初始索引 遍历数组,利用if判断那个位置为控制,在customerview将输入的的信息赋值在null的索引的位置 如果在遍历没有找到则说明数组已满,需要扩容设计if-else  设计展示客户信息public void showAllCustomers() 1先打印首行信息 2遍历数组,当发现有空值的时候结束 3打印客户信息 设计更新:先找到→再替代 找:利用Customer作为返回值,所以需要返回, public Customer getCustomerByName(String name) Customer customer = null;//如果new完之后返回Customer不能知道是否找到 //输入的名字和数组当中的姓名匹配 /将找到的赋值给我输入的customer 替代:遍历为为空结束 遍历匹配将输入的赋值给customer 设计删除 因为用户信息创建,定义索引,遍历数组,利用传进和当前名字是否相等 先找到删除信息索引 找到第一个空值的位置, 利用遍历更换位置 123null null、 从索引位置我开始删除,到第一个空位结束
数组
常见概念  数组的特点: 1、数组的长度一旦确定就不能修改 2、创建数组时会在内存中开辟一整块连续的空间。 3、存取元素的速度快,因为可以通过[下标],直接定位到任意一个元素。 4.数组本身是引用数据类型,数组中的元素可以是任何数据类型. 数组的分类 ①按照维数;一维,二维.... ②按照数组元素的类型:基本数据类型元素的数组,引用数据类型元素的数组
数组的声明与赋值
一维数组的使用 ①一维数组的声明和初始化 格式1:数据类型[ ] 数组名 = new 数据类型[]{元素1,元素2,元素3...}; 格式2:数据类型[ ] 数组名; 数组名 = new 数据类型[ ]{元素1,元素2,元素3...}; >int[ ] ids; >ids = new int[ ]{1001,1002,1003,1004}; >String [] names >names =new String[5 ];//动态初始化 ②如何调用数组的指定位置的元素 →通过角标的方式进行调用(数组的角标或则索引是从0开始的,到数组的-1结束) >String [] names >names =new String[5 ];//动态初始化  ③如何获取数组的长度 属性:length System.out.println(name.length); System.out.println(ids.length); ④如何遍历数组 /*System.out.println(names[0]); System.out.println(names[1]); System.out.println(names[2]); System.out.println(names[3]); System.out.println(names[4]); */ for(i=0;i<names.length;i++){ System.out.println(names[i]); } ⑤数组元素的默认初始化值 >数组元素是整型:0 >数组元素是浮点型:0.0 >数组元素是char型:0或'\u000'而非数字0 >数组元素是boolean型:false >数组元素是String型:null//意思为空值 ⑥数组的内存解析
课后练习
  1、首先for循环遍历数组index中的所有元素 因为i=0对应index当中的元素2,2又作为外层的角标,所以tel输出为1 然后i=1对应index当中的元素0,0又作为外层的角标,所以tel输出为8 最后字符串进行+=拼接
数组的内存解析
  二维数组的内存解析 
数组的排序与运算
多维数组
面向对象
一、java面向对象学习的三条主线 1java类及类的成员:属性、方法、构造器、代码块、内部类 2面向对象的三大特征:封装性,继承性,多态性 3其他关键字:
创建类与创建对象
类的加载过程
创建对象
对象的内存解析

项目1
Account-Customer
 ---------------------------------------------------------------------------------- package com.atguigu.day14; public class Account { private int id; private double balance; private double annualInterestRate; public Account(int id, double balance, double annualInterestRate) { this.id = id; this.balance = balance; this.annualInterestRate = annualInterestRate; } public int getId() { return id; } public void setId(int id) { this.id = id; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public double getAnnualInterestRate() { return annualInterestRate; } public void setAnnualInterestRate(double annualInterestRate) { this.annualInterestRate = annualInterestRate; } public void withdraw(int amount){ if (balance < amount) { System.out.println("余额不足,取款失败"); return; }else balance -= amount; System.out.println("成功取出:"+amount);} public void deposit(int amount){ if(amount > 0){ System.out.println("存款金额为:"+amount); balance +=amount; System.out.println("当前余额为:"+balance); }else{ System.out.println("存款金额不能为负数"); } } } --------------------------------------------------------------------------------------------- package com.atguigu.day14; public class Customer { private String firstName; private String lastName; private Account account;//类做该类的属性 public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public Account getAccount() { return account; } public void setAccount(Account account) { this.account = account; } } --------------------------------------------------------------------------------------------- public class CustomerTest { public static void main(String[] args) { Account account = new Account(1000,2000,0.0123); Customer customer = new Customer("Jane","Smith");//该客户的账户目前没有赋值,默认为Null //如何将账户的属性赋值给Customer 内存解析图  customer.setAccount(account); 将account赋值给我们的方法形参, 方法在形参又将其赋值给了customer属性 customer.getAccount().deposit(100); customer.getAccount().withdraw(960); customer.getAccount().withdraw(2000); System.out.println("Customer["+customer.getFirstName()+","+customer.getLastName() +"] has a account: id is "+customer.getAccount().getId()); } }
Account-Customer-Bank 涉及对象数组
   ----------------------------------------------------------------------------------- 代码详细在Exercise中的atguigu,day14.bank  
属性与方法
方法的结构
package com.atguigu.test; public class Student { // 属性 public String stuName; public int stuAge; public String stuGender; // 方法 // 一个方法有五个常规部分组成:访问修饰符,返回类型,方法名,参数组,方法体 // 访问修饰符:访问修饰符修饰类的成员。public protected 缺省 private // 返回类型:规定方法返回值的数据类型,如果方法不需要返回值,则标注void。 // 如果规定了返回类型,则方法必须在结束前返回一个该类型的值 // 方法的返回值返回到方法的调用点,任何一个出现在java语言中的数据类型都可以做返回类型 public int sayHello(){ int result = 100; // Java程序的代码必须写在方法体里 // 方法中编写的代码会在调用方法时逐行执行 System.out.println("你好,我叫"+stuName+",我今年" +stuAge+",我是一名"+stuGender+"同学"); return result;// 使用return关键字返回返回值 } public void methodOne(){ System.out.println(4); System.out.println(5); System.out.println(6); } }
方法的调用
 方法的使用中,可以调用当前类的属性和方法。 特殊:方法A中又调用了方法A>递归方法 局部变量溢出  方法中不可以定义方法
基础类型传参和引用类型传参
基本类型传参 package com.atguigu.test; public class CountScore { public int countSum(int lang,int math,int english){//形参也是局部变量,在调用时进行赋值即可 int result = 0; result = lang + math + english; return result; } } ----------------------------------------------------------- package com.atguigu.test; import java.util.Scanner; public class TestCountScore { public static void main(String[] args) { CountScore cs = new CountScore();//创建对象 Scanner input = new Scanner(System.in); System.out.println("请输入语文成绩"); int lang = input.nextInt();对形参进行传参 System.out.println("请输入数学成绩"); int math = input.nextInt(); System.out.println("请输入英语成绩"); int english = input.nextInt(); // 调用带参的方法必须按照方法的要求传参(参数类型要求,参数个数要求,参数顺序要求) //int result = cs.countSum(lang,math,english); //System.out.println("总分:"+result); System.out.println("总分:"+cs.countSum(lang,math,english)); } } 引用数据类型传参 假设计算10个科目的分数时?方法的参数很少会超过五个 在调用带参方法时候的方法 1传参(准备参数)→上图,一个方法在声明时候形参太多,在传参的时候会特别麻烦 当调用带参方法不传参则会报错; 1、创建一个类  2,定义一个类为形参 package com.atguigu.test; public class CountScore1 { public int countSum(Score score){ //该形参为一个类的对象,一个形参;new对象是对对象赋值,形参的位置不应该有值,类是引用数据类型 //假设为十门课程时,仍然为一个形参,只需要给对象多定义几个属性即可 int result = 0; // result = score.lang + score.math + score.english;//分数放在对象的属性上,去跟属性要值 result = score.sum(); return result; } public int countAvg(Score score){ int avg = 0; // avg = (score.lang + score.math + score.english) / 3; // 本类的方法调用自己类的方法时可以直接写方法名调用 // avg = countSum(score) / 3; avg = score.avg(); return avg; } } 3, public class TestCountScore1 { public static void main(String[] args) { CountScore1 cs = new CountScore1();创建对象 Scanner input = new Scanner(System.in); System.out.println("请输入语文分数"); //需要用那个类,对象中的属性时需要new,才能够时候,实例化 Score score = new Score();//该对象创建之后属性是没有值的,没有被赋值默认值为0 score.lang = input.nextInt();//赋值,值传给方法,方法对其进行拆分,然后(result)+,然后进行返回。 System.out.println("请输入数学分数");//前面进行输入数值的时候一定是对象.属性进行输入赋值 score.math = input.nextInt(); System.out.println("请输入英语分数"); score.english = input.nextInt(); int sum = cs.countSum(score); //前面进行输入数值的时候一定是对象.属性进行输入赋值 System.out.println("总分:"+sum); int avg = cs.countAvg(score); System.out.println("平均分:"+avg); } }
值传递和引用传递
值传递: 在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。 ----------------------------------------------------------------------------------- 1public static void valueCrossTest(int age,float weight){ 2 System.out.println("传入的age:"+age);25 3 System.out.println("传入的weight:"+weight);77.5 4 age=33; 5 weight=89.5f; 6 System.out.println("方法内重新赋值后的age:"+age);33 7 System.out.println("方法内重新赋值后的weight:"+weight);89.5 8 } 9 10//测试 11public static void main(String[] args) { 12 int a=25; 13 float w=77.5f; 14 valueCrossTest(a,w); 15 System.out.println("方法执行后的age:"+a);//25 16 System.out.println("方法执行后的weight:"+w);//77.5 17} -------------------------------------------------------------------------------------------------------- 引用传递: ”引用”也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向通愉快内存地址,对形参的操作会影响的真实内容。  -----------------------------------------------------------------------------------
属性和局部变量
package com.atguigu.morningtest; import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput; import org.w3c.dom.ls.LSOutput; /* 类中属性的使用 属性(成员变量)vs 局部变量 1相同点 1.1定义变量的格式,数据的类型 变量名 = 变量值 1.2先声明后使用 1.3变量都有对应的作用域 2不同点 2.1>在类中声明的位置不同 属性直接定义在类的一对{}中 局部变量,声明在方法中,方法形参,代码块内,构造器形参,构造器内部的变量 局部变量需要初始化进行使用 2.2>关于权限修饰符的不同 属性:可以声明属性时,指明其权限,使用权限修饰符 常用修饰符:private public 缺省 protected 目前大家声明属性时,都是用缺省就可以 局部变量:不可以使用权限修饰符。 2.3>默认初始化值的情况 属性:类的属性,根据其类型都有默认初始化值 局部变量:在调用局部变量之前一定要显示赋值,没有默认初始化值 特别注意:形参在我们调用时进行赋值即可 2.4>二者在内存中加载的位置 属性:加载到堆的空间中 局部变量:加载到栈空间 */ public class UserTest { public static void main(String[] args) { User u1 = new User(); System.out.println(u1.name); System.out.println(u1.age); System.out.println(u1.isMale); u1.talk("日语"); } } class User{ String name; int age; boolean isMale; public void talk(String language){//language:形参,也是局部变量 } public void eat(){ String food = "烙饼";//局部变量 System.out.println("北方人喜欢出:"+food); } }
可变参数
package com.atguigu.test1; public class TestOne { public static void main(String[] args) { int[] nums = {100,200,300}; //假设静态数组有很多个元素,那么准备数组就很不方便 methodOne(nums); // 变长参数组,如果没有参数可以不传, 有几个参数则传几个参数,多个参数间使用逗号分割 methodTwo("10",10.5,10,20,30); //声明的方法要什么给什么,进行传参。 } ---------------------------------------------------------------------------- public static void methodOne(int[] nums){ int sum = 0; for (int i = 0; i < nums.length; i++) { sum += nums[i]; } System.out.println(sum); } ----------------------------------------------------------------------------- // 使用类型...的方式声明变长参数组 // 一个方法的参数列表中,只允许有一个变长参数组 // 变长参数组允许和普通参数同时出现, 但是变长参数组必须在最后一个 public static void methodTwo(String one,double d, int... nums){ //声明的方法要什么给什么,进行传参 int sum = 0; for (int i = 0; i < nums.length; i++) { sum += nums[i]; } System.out.println(sum); } }
递归
   3----------------------------------------------------------------------------------   ---------------------------------------------------------------------------------   
方法重载
package com.atguigu.test1; //方法的重载存在的意义 //多个方法,每个重载的方法都是一个独立的方法,都有自己的方法体 //方便调用点,语法是在同一个类中方法名相同,参数组不同,在调用的时候依靠传不同的参数调用不同的方法 例如 1,比较两个数据是否相等。参数类型分别为两个byte类型,两个short类型,两个int类型,两个long类型,并在main方法中进行测试。 2,用重载实现:定义方法求两个整数的最大值,定义方法求三个整数的最大值,定义方法求两个小数的最大值。   public class Teacher { //1.定义:在同一个类中允许存在一个以上的同名方法,只要他们的参数个或者参数类型不同即可 //“两同一不同”: //同一个类,相同的方法名字 // 参数列表不同,参数个数不同,参数类型不同 // 方法重载必须在同一个类中,方法名相同,参数组不同(参数个数不同,参数类型不同,参数顺序不同)则构成方法重载 //与方法的权限修饰符 返回值类型,形参变量名,方法体都无关 public void sayHello(){ System.out.println("你好,我是一名老师"); } public void sayHello(int i){ System.out.println("你好,我是一名老师"+i); } public void sayHello(String s){ System.out.println("你好,我是一名老师"+s); } public void sayHello(int i,String s){ System.out.println("你好,我是一名老师"+i+"-"+s); } public void sayHello(String s,int i){ System.out.println("你好,我是一名老师"+s+"-"+i); } public static void main(String[] args) { Teacher teacher = new Teacher(); teacher.sayHello("hello"); } }
对象数组
数组是用来存储一组数据的容器,一组基本数据类型的数据可以用数组装,那么一组对象也可以使用数组来装。 即数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用数据类型是,我们称为对象数组。 --------------------------------------------------------- 练习一 (1)定义圆Circle类,包含radius半径属性,getArea()求面积方法,getPerimeter()求周长方法,String getInfo()返回圆对象的详细信息的方法 (2)在测试类中创建长度为5的Circle[]数组,用来装5个圆对象,并给5个圆对象的半径赋值为[1,10)的随机值 提示: //创建5个对象,半径随机赋值为[1,10)的随机值 //Math.random()==>[0,1) //Math.random()*9==>[0,9) //Math.random()*9+1==>[1,10) ----------------------------------------------------------------- package com.atguigu.morningtest; public class Circle { int radius; public double getArea(){ return Math.PI*radius*radius; } public double getPerimeter(){ return 2*Math.PI*radius; } public String getInfo(){ return "圆的半径为:"+radius+",面积为:"+getArea()+"周长为“"+getPerimeter(); } } ---------------------------------------------------------------------------- class Test16_ObjectArray{ public static void main(String[] args){ 要在数组中存储5个圆对象 //声明一个可以用来存储圆对象的数组 Circle[] arr = new Circle[5]; //给元素赋值,元素为引用数据类型,应该给它一个Circle的对象 //arr[0] = 1.2;//错误的//arr[0]相当于它是一个Circle类型的变量,也是对 象名,必须赋值为对象 /* arr[0] = new Circle(); arr[0].radius = 1.2; System.out.println(arr[0].radius); */ for(int i=0; i<arr.length; i++){ arr[i] = new Circle(); //有对象才有半径 arr[i].radius = Math.random()*9+1; } //遍历显示圆对象的信息 for(int i=0; i<arr.length; i++){ //arr[i]是一个Circle的对象,就可以调用Circle类中的属性和方法 System.out.println(arr[i].getInfo()); } } } ---------------------------------------------------------- 练习2 class Student{ String name; int score; public String getInfo(){ return "姓名:" + name + ",成绩:" + score; } } ---------------------------------------------------------- 方法一 创建对象 给对象当中的元素对象arr[0] = new 对象名(); 有对象才会有属性 一一进行赋值操作 public class ObjectArrayTest { public static void main(String[] args) { Student[] arr = new Student[3]; arr[0] = new Student(); arr[0].name = "张三"; arr[0].score = 89; arr[1] = new Student(); arr[1].name = "李四"; arr[1].score = 84; arr[2] = new Student(); arr[2].name = "王五"; arr[2].score = 85; 方法二 从键盘输入 class Test18_ObjectArrayExer2_2{ public static void main(String[] args){ //创建一个可以装3个学生对象的数组 Student[] arr = new Student[3];//只是申明这个数组,可以用来装3个学生,此时里面没有学生对象 //从键盘输入 java.util.Scanner input = new java.util.Scanner(System.in); for(int i=0;i<arr.length; i++){ System.out.println("请输入第" + (i+1) + "个学生信息:"); arr[i] = new Student();//给元素对象才能访问属性 System.out.print("姓名:"); arr[i].name = input.next(); System.out.print("成绩:"); arr[i].score = input.nextInt(); }
面向对象
面向对象:强调具备功能的对象,以类/对象为最小单位,考虑谁来做的问题 面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做问题 面向过程:当需要实现一个功能时,每个具体的步骤都要亲力亲为,详细处理每个细节。(强调过程) 面向对象:当需要实现一个功能时,不关心具体的步骤,而是找一个已经具有该功能的的人或物体,通过该人或物体来实现这个功能。(强调对象) 面向对象编程(Object Oriented Programing,OOP)的本质:以类的方式组织代码,以对象的组织(封装)数据。 面向对象的三大基本特征:封装、继承和多态。 类:是一组相关属性和行为的集合,可以看成是一类事务的模板,使用事物的属性特征和行为特征来描述该类事物。 属性:就是该事物的状态信息。 行为:就是该事物能够做什么。 对象:是一类事物的具体体现,对象是类的一个实例,必然具备该类事物的属性和行为。 类与对象的关系 类是对一类事物的描述,是抽象的。 对象是一类事物的实例,是具体的。 类是对象的模板,对象是类的实体。 ————————————————
对象的使用
创建对象: 类名 对象名 = new 类名(); 用对象访问类中的成员: 对象名.成员变量; 对象名.成员方法(); 对象的使用格式举例: 对应到Java的类当中: 成员变量(属性): String name; // 姓名 int age; // 年龄 成员方法(行为): public void eat() {} // 吃饭 public void sleep() {} // 睡觉 public void study() {} // 学习 注意事项: 1. 成员变量是直接定义在类当中的,在方法外边。 2. 成员方法不要写static关键字。 */ public class Student { // 成员变量 String name; // 姓名 int age; // 姓名 // 成员方法 public void eat() { System.out.println("吃饭饭!"); } public void sleep() { System.out.println("睡觉觉!"); } public void study() { System.out.println("学习!"); } } 成员变量默认值 
对象的内存图
一个对象调用一个方法的内存图   两个对象调用一个方法的内存图  将一个对象赋值给另外一个对象的内存图   使用对象作为方法参数内存图   使用对象类型作为方法返回值内存图  
成员变量和局部变量
 (1)在类中的位置不同 成员变量:类中,方法外 局部变量:方法中或者方法声明上(形式参数) (2)作用范围不一样 成员变量:类中 局部变量:方法中 (3)初始值不同 成员变量:有默认值 局部变量:没有默认值,必须定义,赋值,最后使用 (4)在内存中的位置不同 成员变量:堆内存 局部变量:栈内存 (5)生命周期不同 成员变量:随着对象的创建而存在,随着对象的消失 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
封装
封装概述
为什么进行封装? 高内聚:类的内部数据操作细节自己完成,不允许外部干涉; 低耦合:仅对外暴露少量的方法用于使用 -------------------------------------------------
成员变量属性私有化问题
成员变量封装的目的 隐藏实现细节 让访问者只能通过预定的方法访问数据,限制对成员变量的不合理访问。 便于修改,提高代码的可维护性 ------------------------------------------------------------------------- 实现步骤 1使用 private 修饰成员变量  2提供 getXxx方法 / setXxx 方法,可以访问成员变量,代码如下:  ------------------------------------------------------------------------------------------------------------------------------ 3、如何解决局部变量与成员变量同名问题 当局部变量与类变量(静态成员变量)同名时,在类变量前面加“类名." private static String country;//静态成员变量(类变量) public static void setCountry(String country){局部变量 Chinese.country = country;类变量对象下的局部变量 } 当局部变量与实例变量(非静态成员变量)同名时,在实例变量前面加“this.” private int age; public void setAge(int age) { this.age = age; }
构造器
构造器的作用 在创建对象的时候为实例变量赋初始值。 语法格式 【修饰符】 构造器名(){ // 实例初始化代码 } 【修饰符】 构造器名(参数列表){ // 实例初始化代码 } -------------------------------------------------------------- public class Student { private String name; private int age; // 无参构造 //类中有任何一个显式的构造方法,则默认隐式无参的构造方法消失 public Student() {} // 有参构造 public Student(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 注意事项 如果一个类没有任何一个显示的构造方法,则系统给这个类配备隐式无参的构造方法 构造方法在创建对象时进行调用,也只能在创建对象时调用,创建对象必须调用构造方法 构造方法可以为对象进行初始化→准备工作,构造方法进行赋值 无参构造进行赋值与直接给属性赋值无差别,所以利用有参构造方法  利用有参的构造方法机型传参后,直接在main方法中输入即可  
标准javaBean
 ---------------------------------------------------------------------------- public class Student { // 成员变量 private String name; private int age; // 构造方法 public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } // get/set成员方法 public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } //其他成员方法列表 public String getInfo(){ return "姓名:" + name + ",年龄:" + age; } } ----------------------------------------------------------------------------- 测试代码 public class TestStudent { public static void main(String[] args) { // 无参构造使用 Student s = new Student();//利用:方法.set变量(根据变量属性进行赋值); s.setName("柳岩"); s.setAge(18); System.out.println(s.getName() + "---" + s.getAge());//打印 System.out.println(s.getInfo()); // 带参构造使用 Student s2 = new Student("赵丽颖", 18);//直接赋值 System.out.println(s2.getName() + "---" + s2.getAge()); System.out.println(s2.getInfo()); } 
封装
继承
继承的语法
语法结构 【修饰符】 class 父类 { ... } 【修饰符】 class 子类 extends 父类 { ... } 继承特点 父类成员私有化 父类无论是公共,私有的成员均会被子类继承,构造方法无法被继承 子类虽然继承父类的私有属性,但不能直接访问,可以通过Get,set方法。 子类继承后,也可以声明自己的属性,也可以对方法进行重写 ------------------------------------------------------------ 父类方法 public void showNum(){ System.out.println("来电显示号码"); } } 子类重写 public void showNum(){ //调用父类已经存在的功能使用super; super.showNum(); //增加自己特有显示姓名和图片功能 //对方法进行重写时,方法名和形参列表都要一样 System.out.println("显示来电姓名"); System.out.println("显示头像"); ---------------------------------------------------------------- 注意事项:父子类成员变量重名 (1)当父类的成员变量私有化时,在子类中是无法直接访问的,所以是否重名不影响,如果想要访问父类的私有成 员变量,只能通过父类的get/set方法访问; (2)当父类的成员变量非私有时,在子类中可以直接访问,所以如果有重名时,就需要加“super."进行区别。 使用格式:super.父类成员变量名 ----------------------------------------------------------- 重写规定  不能重写情况 静态方法不能被重写 私有等在子类中不可见的方法不能被重写 final方法不能被重写
继承的应用场景
关于重写
// 方法重写发生在父子类中,子类编写一个和父类方法签名一模一样的方法 // 子类将父类的方法重写,则父类的方法会被子类的方法覆盖 // 一旦发生方法重写,则由子类对象调用的方法一定是子类重写之后的方法 // 子类重写父类的方法,子类方法的访问修饰符只能比父类的访问修饰符宽不能比父类的访问修饰符窄 // 子类重写父类方法时,如果父类放的返回类型为void或者基础数据类型,则子类必须和父类一样 // 如果返回类型为引用数据类型,子类重写的方法可以返回父类方法返回类型的子类型 // 如果子类重写的父类方法抛出异常,则子类重写方法可以抛出父类异常的子异常 // private修饰的方法不允许重写
继承
多态
接口
public interface 接口名称 { // 抽象方法 //默认方法 //静态方法 //私有方法 } 接口使用步骤: 接口不能直接使用,必须有一个“实现类”来“实现”该接口。 格式: public class 实现类名称 implements 接口名称 { // … } 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法。 实现:去掉abstract关键字,加上方法体大括号。 创建实现类的对象,进行使用。 注意事项: 如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类 ———————————————— 
抽象方法的使用
————————————————
默认方法的使用
静态方法的使用
静态方法与.class文件相关,只能直接使用接口名调用,不可以通过实现类的类名或实现类的对象调用。 /* 从Java 8开始,接口当中允许定义静态方法。 格式: public static 返回值类型 方法名称(参数列表) { 方法体 } 提示:就是将abstract或者default换成static即可,带上方法体。 */ public interface MyInterfaceStatic { public static void methodStatic() { System.out.println("这是接口的静态方法!"); } } public class MyInterfaceStaticImpl implements MyInterfaceStatic { } /* 注意事项:不能通过接口实现类的对象来调用接口当中的静态方法。 正确用法:通过接口名称,直接调用其中的静态方法。 格式: 接口名称.静态方法名(参数); */ public class Demo03Interface { public static void main(String[] args) { // 创建了实现类对象 MyInterfaceStaticImpl impl = new MyInterfaceStaticImpl(); // 错误写法! // impl.methodStatic(); // 直接通过接口名称调用静态方法 MyInterfaceStatic.methodStatic(); } }
私有方法的使用
接口常量
接口的多实现
接口的多继承
多态 父类引用指向子类对象

引用类型转换
多态
面向对象
项目三:开发团队调度软件

思路
NameListService设计
核心: 创建数组对象:employees = new Employee[EMPLOYEES.length] ⬇ 遍历数组 ⬇ 声明int type = Integer.parseInt(EMPLOYEES[i][0]); ⬇ 根据二维数组当中每行第一列当中的数值利用Switch 去匹配data中该数值为那种类型员工 ⬇ 然后创建对应的对象 1根据项目提供的date类构建大小的employee数组  2再根据date类new出不同的对象  因为设备是一个接口,有三个实现类所以不能直接赋值,声明方法进行赋值  返回设备,所以需要Equipment作为返回类型,二维数组,声明index作为可变形参 3将对象存进数组
具体代码
static关键字
static的属性和方法
package com.atguigu.test1; public class Student { // static关键字修饰类的成员 // static关键字修饰的属性叫静态属性,没有static关键字修饰的属性叫普通属性 public String stuName; public int stuAge; public static String school; // 静态的方法无需创建对象,直接由类名调用,也可以由对象名调用,但是不推荐 // 静态成员只能访问静态成员,不能访问普通成员。普通成员可以访问静态成员也可以访问普通成员 // 在静态成员中不能使用this关键字 public static void methodOne(){ System.out.println("in Student static methodOne()~~~~~~~~~"); // sayHello(); Student stu = new Student();//不能直接访问普通的成员,初始化后去调普通的成员的方法也行 stu.sayHello(); System.out.println(school); // System.out.println(stuName); } public void sayHello(){ System.out.println("hello"); methodOne(); System.out.println(this.stuName);// this关键字是当前对象,this关键字是对象级别的关键字 System.out.println(school); } } ----------------------------------------------------------------------------------------------------------- public class TestStudent { public static void main(String[] args) { // 静态属性无需创建对象,可以由类名直接调用,类名.属性名 // 静态属性随着类的加载在方法区分配空间,普通属性随着对象的创建在堆里分配空间 // 静态属性属于类,所有该类对象共用一个静态属性,普通属性属于对象,每个对象拥有自己独立的普通属性 // Student.school = "尚硅谷"; // System.out.println(Student.school); // 普通属性必须创建对象才能调用,由对象名.属性名的方式调用 Student stu = new Student(); stu.stuName = "Tom"; stu.stuAge = 20; stu.school = "尚硅谷"; // System.out.println(stu.school);// 静态属性也可以由对象名调用,但是不推荐 Student stu1 = new Student(); System.out.println(stu1.stuName); System.out.println(stu1.school); stu1.school = "清华"; System.out.println(stu.school); Student.methodOne();// 静态方法直接由类名调用 } }
封装之后需要使用其中的方法,直接将方法声明为静态方法,直接由类名进行调用
静态代码块
Java静态代码块的作用:Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次,也就是说这些代码不需要实例化类就能够被调用。 一般情况下,如果有些代码必须在项目启动的时候就执行的时候,就需要使用静态代码块。 Java静态代码块的用法:一个类可以使用不包含在任何方法体中的静态代码块,当类被载入时,静态代码块被执行,且只被执行一次,静态块常用来执行类属性的初始化。 实操⬇ /* 工具类 */ public class JDBCUtils { private static String driverClassName = ""; private static String url = ""; private static String username = ""; private static String password = ""; private static FileInputStream fis = null; static{// try { //读取配置文件中的内容 //1.创建Properties对象 Properties properties = new Properties(); //2.创建流 FileInputStream fis = new FileInputStream("jdbc.properties"); //3.加载流 properties.load(fis); //4.读取数据 username = properties.getProperty("username"); password = properties.getProperty("password"); driverClassName = properties.getProperty("driverClassName"); url = properties.getProperty("url"); }catch (Exception e){ //终止程序的运行(将编译时异常转换成运行时异常) e.printStackTrace(); throw new RuntimeException(e.getMessage()); }finally { //5.关流 if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static Connection getConnection() { try { //为了执行类加载让静态代码块执行。 Class.forName(driverClassName); //获取数据库连接对象 Connection connection = DriverManager.getConnection(url, username, password); return connection; }catch (Exception e){ //终止程序的运行(将编译时异常转换成运行时异常) e.printStackTrace(); throw new RuntimeException(e.getMessage()); } } /* 关闭资源 */ public static void close(PreparedStatement ps, Connection connection) { if (ps != null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(PreparedStatement ps, Connection connection, ResultSet resultSet) { close(ps,connection); if (resultSet != null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } } } 在父子类状态下,先父类再子类,先静态再普通。在属性,再代码块再构造方法 在单个类的状态下先静态再普通,先属性再代码块,最后构造方法 ---------------------------------------------------------------------- package com.atguigu.test; // 在父子类状态下,先父类再子类,先静态再普通。在属性,再代码块再构造方法 public class Person { private int one = methodThree(); private static int two = methodFour(); static {//静态代码块 System.out.println("in Person static stock"); } { System.out.println("in Person stock"); }//普通代码块 public Person() {//构造方法 System.out.println("in Person()"); } public int methodThree(){ System.out.println("in Person methodThree()"); return 10; } public static int methodFour(){//静态方法 System.out.println("in Person static methodFour()"); return 20; } } ------------------------------------------------------------------------------------- package com.atguigu.test; // 在单个类的状态下先静态再普通,先属性再代码块,最后构造方法 public class Student extends Person{ private String stuName; private int stuAge = methodOne(); public static String school = methodTwo();//静态 static { System.out.println("in static stock one"); } { System.out.println( "in stock one"); } public Student() { System.out.println("in Student()"); } public int methodOne(){ System.out.println("in methodOne()"); return 10; } public static String methodTwo(){ System.out.println("in static methodTwo()"); return "name"; } } -------------------------------------------------------------------------------------父类静态方法 父类静态代码块 子类静态方法 子类静态代码快 父类普通方法 父类普通代码快 父类构造 子类普通方法 子类普通代码块 子类构造 在父子类状态下,先父类再子类,先静态再普通(方法)。在属性,再代码块再构造方法 在单个类的状态下先静态再普通方法,先属性再代码块,最后构造方法
一个类可以使用不包含在任何方法体中的静态代码块,当类被载Class.forname入时,静态代码块被执行,且只被执行一次,静态块常用来执行类属性的初始化。
Static应用
懒汉式单例设计模式
饿汉式设计模式
final关键字
首先final关键字能修饰什么结构:类;方法;变量,属性,参数。 static修饰的方法不能被重写: Static修饰的方法是被类名调用的,调用时机和普通方法不一样,不合适用重写语法 private修饰的方法不能被重写 看不见,不能用,当然不能重写 final,语法规定不能重写 -----------------------------------------------------------
包装类
为什么需要包装类? JAVA是面向对象的语言,很多类和方法中的参数都需使用对象(例如集合),但基本数据类型却不是面向对象的,这就造成了很多不便。 如:List<int> = new ArrayList<>();,就无法编译通过 为了解决该问题,我们引入了包装类,顾名思义,就是将基本类型“包装起来“,使其具备对象的性质,包括可以添加属性和方法,位于java.lang包下。 ————————————————  -----------------------------------------------------------------------------  ----------------------------------------------------------------------------- 装箱与拆箱 基本数值→包装对象 Integer i1 = new Integer(4);//使用构造函数函数 Integer i2 = Integer.valueOf(4);//使用包装类中的valueOf方法 包装对象→基本数值 Integer i1 = new Integer(4); int num1 = i1.intValue(); ----------------------------------------------------------------------------- Integer i = 4;//自动装箱。 相当于Integer i = Integer.valueOf(4); i = i + 5; //等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5; //加法运算完成后,再次装箱,把基本数值转成对象。  对象与String  变量与String  -----------------------------------------------------------------------------  
接口
接口的语法
接口不允许实例化 一个接口可以有多个实现类,每个实现类实现不同的接口方法效果 接口中的属性默认修饰是public static final 接口中声明的方法默认是public abstract 公开的默认方法public可以省略,default不可以省略 公开的静态方法Static不能省略 -------------------------------------------------------- package com.atguigu.test1; public interface Person { public static final String NAME = "Tom"; public abstract void sayHello(); } ------------------------------------------------------------------------ package com.atguigu.test1; public interface Coder { public void coding(); } ------------------------------------------------- Teacher implements Person Teacher实现Person接口,Teacher是Person的实现类 一个类实现了一个接口,则必须实现接口中所有的abstract方法 实现类实现接口不影响继承,继承父类和实现接口可以同时存在 java的类采用单继承多实现效果,一个类可以实现多个接口,多个接口间用逗号分割 一个类实现了多个接口,那么任何一个它实现的接口需要对象时,都可以传递当前类的对象 -------------------------------------------------------------------------------- public class Teacher extends Object implements Person,Coder {//实现多个接口 @Override public void sayHello() { System.out.println("你好,我是一名老师"); } @Override public void coding() { System.out.println("编写代码"); } } ------------------------------------------------------------------------------------------- package com.atguigu.test1; public class Student implements Person { @Override public void sayHello() { System.out.println("你好,我是一名学生"); } } --------------------------------------------------------------------------------- package com.atguigu.test1; public class TestTwo { public static void main(String[] args) { Teacher teacher = new Teacher();//创建实现类的对象 //多态的方式创建teacher对象, Person p = teacher; p.sayHello(); Coder c = teacher; c.coding(); } }
接口使用上 也满足多态性
练习 接口使用上也满足多态性 接口实际上定义了一种规范 ----------------------------------------------------------------------- public interface USB { public abstract void start(); public abstract void stop(); } ---------------------------------------------------------------- 两个实现类flash和printer public class Printer implements USB{ @Override public void start() { System.out.println("打印机开始工作"); } @Override public void stop() { System.out.println("打印机停止工作"); } } -------------------------------------------- public class Flash implements USB { @Override public void start(){ System.out.println("U盘开始工作"); } @Override public void stop(){ System.out.println("U盘停止工作"); } } ----------------------------------------------------------------------------- public class Computer { //创建一个方法以接口USB作为形参传递实现类的方法 public void transferDate(USB usb){ usb.start(); System.out.println("具体的传输数据的细节"); usb.stop(); } } -------------------------------------------------------------------------------------- 测试 public class TestUSB { public static void main(String[] args) { Computer com = new Computer(); //1,创建了接口的非匿名实现类的非匿名对象 Flash flash = new Flash(); //2,创建了接口的非匿名实现类的匿名对象 com.transferDate(new Printer());有名实现类 //3创建了接口的匿名实现类的非匿名对象 USB phone = new USB(){//匿名实现类拿USB充当一下 phone为对象有名字 @Override public void start(){ System.out.println("手机开始工作"); } @Override public void stop(){ System.out.println("手机停止工作"); } }; com.transferDate(phone); //4创建了接口的匿名实现类的匿名对象  实现类没有名字,接口充当,new的对象也没有名字 com.transferDate(flash); //本身接口不能创建对象,只能创建实现类的对象 Printer pri = new Printer(); com.transferDate(pri); } } ---------------------------------------------------------------------- 在实际的开发过程中,如果只使用一次一般根据情况选择234
接口的应用场景
当多个对象不能够抽象出共同的父类,但有共同的行为,这种情况下就需要将这种行为封装成接口。比如:登记这种行为:人,汽车,房子,都需要等级 ,但是这三类没有共同的特征。所以要单独将这一行为封装成一个接口。再如:电脑的USB接口,如果符合USB接口规范,就可以插进去,并且读取数据,但是iphone ,Mp3,U盘他们不是同一种类型。所以USB接口规范就要单独写了。 ————————————————
面向接口编程
内部类
package com.atguigu.test1; public class Outer { private int three; private static int four; 静态成员内部类 // 静态成员内部类可以声明静态成员,也可以声明普通成员 // 静态成员内部类不能访问外部类的普通成员,只能访问外部类的静态成员 // 内部类可以访问外部类的私有成员 public static class Inner{ private int one; private static int two; public void methodOne(){ //System.out.println(one); System.out.println(two); // System.out.println(three); System.out.println(four); // methodThree(); methodFour(); } public static void methodTwo(){ // System.out.println(one); System.out.println(two); // System.out.println(three); System.out.println(four); // methodThree(); methodFour(); } } public void methodThree(){ Inner.two = 200; Inner.methodTwo(); // 在外部类类体内创建内部类对象 // 在外部类类体内,内部类就是一个正常的类 Inner inner = new Inner(); inner.one = 100; inner.methodOne(); } public static void methodFour(){ } } ------------------------------------------------------------------------- package com.atguigu.test1; public class Outer1 { private int three; private static int four; 普通成员内部类 // 普通成员内部类只能声明普通成员不能声明静态成员 // 普通成员内部类可以访问外部类的所有成员 public class Inner1{ private int one; // private static int two; public void methodOne(){ System.out.println(one); System.out.println(three); System.out.println(four); methodThree(); methodFour(); } // public static void methodTwo(){ // // } } public void methodThree(){ // 在外部类类体内就像一个普通的类一样创建内部类对象 Inner1 inner1 = new Inner1(); } public static void methodFour(){ } } -------------------------------------------------------------------------------- public class Outer2 { private int three; private static int four; public void methodOne(){ int five = 100; // 局部内部类 // 局部内部类只能声明普通成员不能声明静态成员 class Inner2{ private int one; // private static int two; public void methodOne(){ System.out.println(one); System.out.println(three); System.out.println(four); System.out.println(five); } } Inner2 inner2 = new Inner2(); } public void methodTwo(){ // Inner2 inner2 = new Inner2(); } }
匿名内部类
匿名内部类的基本格式 →new 类名或接口名(){ //重写方法 }; 我们平时new一个对象的基本格式为类名或接口名 对象名=new 类名或接口名(),形式上是有区别的,但两者其实都是新建了个对象,不要被名字中有个类搞混。重写方法常见于子类继承父类和子类实现接口。 本质:一个继承该类或实现该接口的子类的匿名对象。 使用方式: 如下创建People类,类中有run()方法。  新建一个Teacher类继承People类,重写其run()方法,如下  Demo类如下  --------------------------------------------------------------------------------------------------------------------------------------- 使用匿名内部类  ----------------------------------------------------------------------------------------------------------------------------------------- 匿名内部类的作用 从上面的两个方法中,我们可以看出第二个方法少建了一个类,通过在匿名对象内重写方法,再通过匿名对象调用,我们达成了与方法一同样的效果,实际上匿名内部类的优点就在于此如果我们需要System.out.println("工人在跑步");,我们不需要再新建一个Worker类继承People类,然后重写run()方法,再通过新建对象调用。同理如果还有学生,农民,程序员等等,我们可以少建很多类,大大简化整个项目的结构。 那么重点来了,匿名内部类的适用范围是“一次就好,我带你去往天涯海角”, 比如上面需要多次输出System.out.println("老师在跑步"),那么Demo类就会变成这样: 
异常
异常的处理过程 1当运行代码时,发生异常,此时程序就会停下,将异常信息封装到异常的对象中,抛出 2Jvm此时就会检查该代码外围是否有try{}catch(){} 如果有就判断是否捕获异常,如果捕获了就抛出异常,程序就进入对应的catch块进行异常处理 接着运行接下的代码 3JVM会检测在这段程序代码的外围,根本就没有try...catch或者是有try...catch但是捕获不住,即类型对不上,JVM都会把这个异常对象抛出“上级,方法的调用者” 4上级一旦接到异常对象,处理过程还是1,2,3 5如果一直抛,一路上都没有可以捕获它,程序就崩溃了。 // 异常也叫运行时错误 // 在出现异常的那行代码,系统会创建一个该类异常的对象,向上抛出 // 如果这个异常对象抛给了虚拟机,则虚拟机会立即终止当前进程 ------------------------------------------------------- public class TestTwo { public static void main(String[] args) { // Class.forName(""); // Thread.sleep(100); try-catch处理方式 // try块负责监控可能出现异常的代码 try { System.out.println("in try one"); Scanner input = new Scanner(System.in); System.out.println("请输入被除数"); int one = input.nextInt(); System.out.println("请输入除数"); int two = input.nextInt(); int result = one / two;// 在出现异常的那行代码创建异常对象,向上抛出 System.out.println("result="+result); System.out.println("in try two"); }catch (ArithmeticException ex){ // 当try块监控到抛出的异常对象时,catch块会根据自己参数类型匹配捕获抛出异常对象,如果捕获成功则进入catch块 // 进入catch块,执行catch块代码,catch块执行完毕则程序继续向下执行 // 多重catch块会从第一个catch开始匹配异常,匹配成功执行catch块,执行完毕跳出整个try-catch结构向下继续执行 如果匹配异常不成功,则继续向下匹配下一个catch块的异常 System.out.println("in catch"); ex.printStackTrace(); }catch (InputMismatchException ex){ System.out.println("in catch two"); ex.printStackTrace(); }catch (Exception ex){ ex.printStackTrace(); } System.out.println("程序结束"); } } ------------------------------------------------------------------ try-catch-finally结构 try块不能单独出现,try块可以和catch块同时出现 try块也可以和finally块同时出现 try块和catch块finally块同时出现 无论是否出现异常,都会执行finally块,甚至在上面有return的情况都可以执行 ---------------------------------------------------------------------------------------------------------------------------------------------------------- throw new 异常类名(参数); throw抛出手动创建的异常对象
练习
package com.atguigu.day13; import java.util.Scanner; public class T2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入三角形的三条边a,b,c"); //对形参进行赋值 int a = scanner.nextInt(); int b = scanner.nextInt(); int c = scanner.nextInt(); try{ triangle(a,b,c);//静态方法直接由方法名调用 }catch (IllegalArgumentException e){ e.printStackTrace(); } } //关键字throws**运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常) public static void triangle(int a, int b, int c)throws IllegalArgumentException{//方法必须为静态方法 if ((a + b) > c && (a + c) > b &&(c + b )> a) { System.out.println("a,b,c三边能够构成三角形,a,b,c分别为"+a+","+b+","+c); }else { throw new IllegalArgumentException(); } } }
自定义异常
 1继承Exception 2提供无参构造和有参构造 ----------------------------------------------------------------------------------- 应用 
异常分类
  受检异常必须处理(利用(throws或try...catch),非受检异常一般不处理(编译器无法检测) ---------------------------------------------------------------------------------- 常见 运行时异常: 数组下标越界异常:ArrayIndexOutOfBoundsException 类型转换异常:ClassCastException 算术异常:ArithmeticException 空指针异常:NullPointerException 编译时异常: IO操作异常:IOException 文件找不到异常:FileNotFoundException 已到达文件流末尾异常:EOFException 类找不到异常:ClassNotFoundException 没有对应的方法异常:NoSuchMethodException
Object根父类
引用数据类型利用==比较,比较的是两个对象的地址值,不能比两个对象是否相等;比的是堆空间是否相等; 而基本数据类型在栈空间可以直接进行比较 如图  ==比引用,比引用上的地址,表示指向同一堆空间的同一对象 由此都出结论引用类型进行比较要用equals ---------------------------------------------------------------- 关于重写String 意义:to String 和getInfo的本质区别是在于一个自动调用,一个是需要手动调用;  如上图,实例化后可以直接进行打印stu=stu.toString ---------------------------------------------------------------- 重写equals 意义:引用数据类型==比较的是地址值,指向堆空间的同一位置  new两个对象,指向堆空间位置位置不同则为false 利用equals返回为true必须为两个对象三个属性必须相同 @Override // public boolean equals(Object obj) { // boolean flag = false;//方法有返回类型的时候先确定该类型的一个变量 // if(this == obj){//遇到两个引用指向同一个对象的情况 // flag = true;//在初始值为false的情况下什么时候改为true // }else{//当不指向堆空间同一位置时。两个new要求两个对象的属性完全相同 // if(obj instanceof Student){//this是student // Student stu = (Student)obj; // if(this.getStuName().equals(stu.getStuName()) // &&this.getStuAge() == stu.stuAge// 基本数据类型用==,引用数据类型用equals // &&this.getStuGender().equals(stu.getStuGender())){ // flag = true;//原则就是两个对象三个属性完全相等则相等 // } // } // } // return flag; // }
练习
 -------------------------------------------------------------------------------------- 
枚举
7.1.3 JDK1.5之后 语法格式: enum关键字声明的枚举的构造方法默认为private enum声明的枚举必须在第一部分编写本类的属性 默认修饰在enum中不能写出,否则报错,public修饰为了被外界访问,public static为了利用类名直接调用,final目的在赋值完初始值之后不能改,Season,Spring作为本类的对象所以一定是Season可以省略,Spring作为Spring的关键字必须调season的构造方法也可以不写 -------------------------------------------------------- 
反射
https://blog.csdn.net/ju_362204801/article/details/90578678 方法区的类类的为类类对象
获取class类对象的四种方法
public static void main(String[] args) { // 获取Class类对象的四种方式 Class classOne = Student.class;// 类名.class的方式获取类类对象 System.out.println(classOne.getName()); Student stu = new Student(); Class classTwo = stu.getClass();// 对象名.getClass()方法获取类类对象 Class classThree = null;//初始化 try { // 使用Class的方法forName获取类类对象 classThree = Class.forName("com.atguigu.test1.Student"); } catch (ClassNotFoundException e) { e.printStackTrace(); } 其中class.forName也可以用来触发类加载执行静态代码块  Class classFour = null; try { // 使用类加载器获取类类对象 classFour = Student.class.getClassLoader().loadClass("com.atguigu.test1.Student"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
class类的常见方法
Class classOne = Student.class;//创建类类对象 System.out.println(classOne.getName()); // 获取类类对象代表的类的完整类名 System.out.println(classOne.getSimpleName()); // 获取类类对象代表的类的不包含包名的类名 Field[] fields = classOne.getFields(); // 返回类下所有的公开属性,可以包含从父类继承的公开属性 Field[] fields1 = classOne.getDeclaredFields(); // 返回类下所有修饰符的属性,仅限本类 -----------------------关于属性------------------------------------- try { Field field1 = classOne.getField("one"); // 根据属性名返回公开修饰的该属性对象,包含从父类继承到的 System.out.println(field1); } catch (NoSuchFieldException e) { e.printStackTrace(); } try { Field field2 = classOne.getDeclaredField("stuAge"); // 根据属性名返回所有修饰的属性对象,仅限本类 System.out.println(field2); } catch (NoSuchFieldException e) { e.printStackTrace(); } 1,获取根据属性名得到的公开修饰的属性对象,不仅限本类,包括继承得到的属性 2,获取根据属性名得到的所有修饰符修饰的属性对象,仅限本类 3,获取所有公开修饰的属性数组,不仅限本类,包括继承得到的属性 4,获取所有的修饰符修饰的所有属性数组,仅限本类  ----------------------------关于方法 ------------------------------- Method[] methods = classOne.getMethods(); // 返回所有公开修饰的方法,包含从父类继承到的 for (Method method : methods) { System.out.println(method.getName()); } System.out.println("------------------------------------------------"); Method[] methods1 = classOne.getDeclaredMethods(); // 返回所有修饰符修饰的所有方法,仅限本类 for (Method method : methods1) { System.out.println(method.getName()); } try { Method method1 = classOne.getMethod("methodOne",String.class,int.class,double.class); // 根据方法名返回公开修饰的方法,包含从父类继承的 System.out.println(method1); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { Method method2 = classOne.getDeclaredMethod("getStuAge"); // 根据参数返回所有修饰符修饰的该方法,仅限本类 } catch (NoSuchMethodException e) { e.printStackTrace(); } ---------------------------关于构造器------------------------------ Constructor[] constructors = classOne.getConstructors(); // 获取所有公开修饰的构造器 Constructor[] constructors1 = classOne.getDeclaredConstructors(); // 获取所有修饰符的所有构造器 Constructor constructor = classOne.getConstructor(); // 获取公开修饰无参构造器 // Constructor constructor = classOne.getConstructor(String.class,int.class,String.class); // 获取公开修饰带参构造器 Constructor constructor =classOne.getDeclaredConstructor(); // 获取所有修饰的无参构造器 // Constructor constructor =classOne.getDeclaredConstructor(String.class,int.class,String.class); // 获取所有修饰的带参构造器
反射利用属性找对象
常规对象找属性  -----------------------------反射利用属性找对象-------------------------------------------- 1公开属性  具体实现 先拿到类类对象 Class classOne = Student.class 属性找对象,创建属性 拿属性 在利用属性找对象  该对象为Student类对象,所以需要去创建  2私有属性→属性私有,正常情况不能访问  反射中 设置私有属性的公开访问(暴力破解)  公开静态  3静态属性和对象无关 
方法
获取方法的相关信息
Class classOne = Student.class; Method[] methods = classOne.getDeclaredMethods(); for (Method method:methods) { System.out.println(method.getName()); //返回整数型的访问修饰符 System.out.println(method.getModifiers()); // 将整数的访问修饰符值转成String String mod = Modifier.toString(method.getModifiers()); System.out.println(mod); System.out.println("获取方法的返回类型------------------"); //获取方法的返回类型 Class returnClass = method.getReturnType();//创建类类对象 System.out.println(returnClass.getSimpleName()); System.out.println("获取方法列表的形参类型 ----------------"); Parameter[] parameters = method.getParameters(); for (Parameter parameter:parameters) { Class typeClass = parameter.getType(); System.out.println(typeClass.getSimpleName()+" "); } }
利用方法调用对象
Class classOne = Student.class; Object obj = classOne.newInstance(); -------------------------利用放射调用公开的方法---------------------------  (方法名,形参类型.class) ---------------------------利用反射调用私有方法------------------------------  利用参数获取方法,区分方法,方法重载两同三不同 破解私有方法 调用方法,破解,传实参   ------------------利用反射调用静态的方法---------------------------------- 静态方法和对象无关  Invoke(对象,实参)
IO流19
描述流的 分类方式和流的特点 按照方向分类:输入和输出流,参照点为程序 按照内容:字节和字符流 按照角色:节点流和处理流,后者依附前者 
file类的常见方法
绝对路径,位置没有限制 以盘符为起点,好找 "D:\\temp\\hello.txt" ------------- 相对路径起点 必须在工程内部 day19\\file\\hello,txt --------------------------------------------------------------------- file.exists判断文件是否存在 file类的常见方法 file.getName返回没有路径的文件名 file.exists()判断文件是否存在 file.createNewFile()创建文件 file.mkdir()创建文件夹,只能创建最后 一级 file.mkdirs()创建文件夹,可以创建多级文件夹 file.delete()删除文件或则文件夹,删除文件,文件夹必须 为空 file.getAbsoluteFile()返回文件的绝对路径 创建的file对象 file.getAbsolutePath();返回文件的绝对路径 ,不考虑 创建方式 file.getCanonicalPanth()抛异常的绝对 路径 (file.getParent());// 返回文件所在文件夹 路径,考虑创建方式 file.getParentFile());// 返回文件所在文件夹路径创建的对象, 考虑创建方式 file.length() 返回文件的大小,返回的是字节数 file.isFile() 判断file对象是否为文件 file.isDirectoty() 判断 file对象代指的是否为文件夹 file.isHidden() 判断文件是否为隐藏文件 file.canRead() 判断文件是否 可读 file.canWrite() 判断文件是否可写 ----------------------------------------------------------------- 
字节流
InputStream
OutputStream
关于复制
  缓冲流 提高效率 ,提供更多的 方法 结尾关闭流
字符流
字符输入流【Reader】
Reader是一个读取文本文件的抽象类 
字符输出流【Writer】

缓冲流
字节缓冲流**:`BufferedInputStream`,`BufferedOutputStream`
*字符缓冲流**:`BufferedReader`,`BufferedWriter`
对象流
对象流:有的时候,我们可能需要将内存中的对象持久化到硬盘上,或者将硬盘中的对象信息读到内存中,这个时候我们需要使用对象输入输出流。 具备读取 对象的 能力 如何实现序列化 (1)实现Serializable接口或Externalizable接口,并且视情况而定指定一个序列化版本ID(serialVersionUID)值;而且要保留公共的无参构造。 (2)如果某个对象的属性也是引用数据类型,那么该数据类型也要实现Serializable接口或Externalizable接口; (3)如果要序列化,则使用一个输出流来构造一个对象输出流ObjectOutputStream并通过writeObject(Object obj)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流ObjectInputStream,然后通过readObject方法从流中读取对象。 (4)如果某些属性不参与序列化,如果是实现Serializable接口的,直接在属性前面加transient修饰,注意:static修饰的属性也不会被序列化,如果是实现Externalizable接口,那么只要在重写writeExternal()和readExternal()方法时,不处理该属性即可。 实现序列化的意义 序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,即把对象的内容转成二进制数据。 可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题) 
ObjectInputStream

ObjectOutputStream

JDK1.8新特性
Lambda表达式
函数式接口
函数式接口只能有一个抽象方法  lambda表达式只能用于 函数式接口 有名内部类→lambda 1创建接口实现类  MyInterOne myInterOne = new MyInterOneImpl(); myInterOne.methodOne(); 2有名内部类实现接口  3lambda表达式 
函数式实现接口的几种方式
// 函数式实现接口的几种方式 MyInterOne myInterOne = new MyInterOne() { @Override public void methodOne() { System.out.println("in innerClass methodOne~~~~~~~~~~~~~~~~~"); } }; myInterOne.methodOne(); ----------- System.out.println("---------------------------------------------"); // lambda表达式实现 // 如果方法的实现体有多行代码,则必须保留方法大括号 MyInterOne myInterOne1 = () -> { System.out.println("in myInterTwo methodOne~~~~~~~~~~~~~~~~~~~~~"); }; // 如果方法的实现只有一行代码,则可以省略大括号 MyInterOne myInterOne2 = () -> System.out.println("in myInterTwo methodOne~~~~~~~~~~~~~~~~~~~~~");  // 单个形参情况下 // 形参给出类型和形参名 MyInterTwo myInterTwo = (String s) -> System.out.println(s); myInterTwo.methodTwo("hello world"); // 形参可以不给类型,只给形参名 MyInterTwo myInterTwo1 = (s) -> System.out.println(s); myInterTwo1.methodTwo("hello world"); // 如果形参只有一个参数,则可以省略小括号 MyInterTwo myInterTwo2 = s -> System.out.println(s); myInterTwo2.methodTwo("hello world"); // 多个形参情况下 // 给出每个参数的参数类型和参数名 MyInterThree myInterThree = (String s,int i) -> System.out.println("s="+s+",i="+i); myInterThree.methodThree("hello",101); // 给出每个参数形参名,省略形参类型,多个形参小括号不可以省略 MyInterThree myInterThree1 = (s,i) -> System.out.println("s="+s+",i="+i); myInterThree1.methodThree("ok",202); } }
系统提供的四大函数式接口
 public class TestFour { public static void main(String[] args) { // 消费型接口 //抽象方法参数,消费即给定参数要对其进行打印,或则给属性赋值 ,写进硬盘文件 Consumer<String> consumer = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }; consumer.accept("hello world"); System.out.println("--------------------------------------");------- Consumer<String> consumer1 = s -> System.out.println(s); consumer1.accept("one world one dream"); System.out.println("--------------------------------------"); // 供给型接口 Supplier<String> supplier = new Supplier<String>() { @Override public String get() { return "tom"; } }; String s = supplier.get();//返回对象接收 System.out.println(s); System.out.println("-----------------------------------------");  // Supplier<String> supplier1 = () -> {return "jerry";}; Supplier<String> supplier1 = () -> "jerry";→有效推断 System.out.println(supplier1.get()); System.out.println("--------------------------------------------");  // 判断型接口 Predicate<String> predicate = new Predicate<String>() { @Override public boolean test(String s) { return s.equals("ok"); } }; boolean flag = predicate.test("ok"); System.out.println(flag); System.out.println("--------------------------------------"); Predicate<Integer> predicate1 = i -> i >= 60; System.out.println(predicate1.test(50)); System.out.println("--------------------------------------");  // 功能型接口 Function<String,Integer> function = new Function<String, Integer>() { @Override public Integer apply(String s) {//给定String返回Integer return new Integer(s); } }; System.out.println(function.apply("100")+1); System.out.println("----------------------------------------"); Function<Integer,String> function1 = i -> i.toString(); System.out.println(function1.apply(200)+2); } }
StreamAPI
StreamAPI作用:条件检索工具,本身 不存储元素和数据 每次处理都会产生新的对象    
创建Stream
1、创建 Stream方式一:通过集合 Java8 中的 Collection 接口被扩展,提供了两个获取流的方法: public default Stream<E> stream() : 返回一个顺序流 public default Stream<E> parallelStream() : 返回一个并行流 2、创建 Stream方式二:通过数组 Java8 中的 Arrays 的静态方法 stream() 可以获取数组流: public static <T> Stream<T> stream(T[] array): 返回一个流 重载形式,能够处理对应基本类型的数组: public static IntStream stream(int[] array):返回一个整型数据流 public static LongStream stream(long[] array):返回一个长整型数据流 public static DoubleStream stream(double[] array):返回一个浮点型数据流 3、创建 Stream方式三:通过Stream的of() 可以调用Stream类静态方法 of(), 通过显示值创建一个流。它可以接收任意数量的参数。 public static<T> Stream<T> of(T... values) : 返回一个顺序流 4、创建 Stream方式四:创建无限流 可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流。 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f):返回一个无限流 public static<T> Stream<T> generate(Supplier<T> s) :返回一个无限流 ----------------------------------------------------------- public class TestTwo { public static void main(String[] args) { // 获取Stream流对象 List<Student> list = StudentData.getList(); // 从集合获取数据形成流对象 Stream<Student> stream = list.stream(); // 终止操作 stream.forEach(stu -> System.out.println(stu)); ---------------------------------------------------------------------------------- Student[] stus = new Student[list.size()]; list.toArray(stus); // 从数组中获取流对象 Stream<Student> stream1 = Arrays.stream(stus); // 终结操作 stream1.forEach(stu -> System.out.println(stu)); --------------------------------------------------------------- // 从散列数据中获取流对象 Stream<String> stream2 = Stream.of("Tom","Jerry","Mary","June"); // 终结操作 stream2.forEach(s -> System.out.println(s)); } } 
中间操作
 ------------------------------------------------------------------------------------------------------- 常用 中间操作方法 public static void main(String[] args) { List<Student> list = StudentData.getList();//获取流对象 for (Student student : list) { System.out.println(student); }//遍历集合与下列方法形成的流进行对比 System.out.println("----------------------------------------------"); //从集合中获取数据形成流对象 Stream<Student> stream = list.stream(); // 中间操作 // Stream<Student> stream1 = stream.distinct();/ / 使用元素的equals方法去掉重复记录 // Stream<Student> stream1 = stream.sorted();// 利用元素自然排序 // Stream<Student> stream1 = // stream.sorted((s1,s2) -> (int)(s2.getScore() * 10 - s1.getScore()*10));// 利用元素定制排序 1----------------- List<Student> list = StudentData.getList(); // Stream<Student> stream1 = stream.limit(15);// 截取到参数之前的数据 // Stream<Student> stream2 = stream1.skip(10);// 截取参数后一位直到末尾的数据 // Stream<Student> stream1 = stream.limit(10).skip(5); // 终结操作 // stream1.forEach(s -> System.out.println(s)); 2------------- 可以将以上部分写成Lambda表达式 Stream.listream.limit(10).skip(5).forEeach(s -> System.out.println(s)); ↓ list.stream().limit(10).skip(5).forEach(s -> System.out.println(s)); ↓ StudentDate.getList().Stream..limit(10).skip(5).forEach(s ->System.out.println(s)); ----------------------------------------------------------------------------------- Filter方法→接收一个判断型接口  条件检索  多条件检索  ==  每次操作产生新对象.调用下一个方法,流是不能 重复 使用的  -----------------------------------------------------------------------------------
终结操作
 List<Student> list = StudentData.getList(); Stream<Student> stream = list.stream(); System.out.println(stream.filter(s -> s.getScore() >= 60).count()); // 统计集合中数量的终结操作 System.out.println(list.stream().allMatch(s -> s.getScore() >= 10)); // 要求数据流中的所有数据都匹配条件 System.out.println(list.stream().anyMatch(s -> s.getScore() >= 100)); // 数据流中任何一条记录满足条件即返回true ---------------------------------------------------------------------------   get如果没有获取到元素会抛出异常  找到即返回 ,没有相当于 初始化,不会 报异常 collect 流每次只能使用一次,因此利用其来收集方便后续假设使用进行操作  collectors接口中方法
集合框架
 
Collection接口
Collection接口是单元素集合 Collection的常用方法 public class TestOne { public static void main(String[] args) { // Collection接口是单元素集合 // Collection的常用方法 Collection col = new ArrayList(); System.out.println(col.size());// 当前集合中的元素数 col.add("Tom");// 将元素添加进集合 col.add("Jerry"); col.add("Mary"); col.add("Tom"); col.add("Tom"); System.out.println(col.size()); System.out.println(col); col.remove("Tom");// 从集合中移除掉参数元素,如果参数元素在集合中有重复,则只移除第一个 System.out.println(col.size()); System.out.println(col); Collection col1 = new ArrayList(); col1.add("Tom"); col1.add("小明"); col1.add("小强"); /* col1.add("小白"); col.addAll(col1);// 一次性向集合中添加参数集合中的所有元素 */ col.add("小明"); col.add("小强"); col.add("小白"); System.out.println(col.size()); System.out.println(col); col.removeAll(col1);// 一次性移除参数集合中的所有元素 System.out.println(col.size()); System.out.println(col); System.out.println(col.contains("Jerry"));// 判断集合中是否包含参数元素 col.clear();// 清空集合 System.out.println(col.isEmpty());// 判断集合是否为空 } } 遍历collection 增强for循环只能遍历,不能移除 
List接口
特点:有下标,有序(新增顺序和遍历顺序一致),允许重复记录 有List独有的方法  List接口的遍历 
ArrayList
public class TestFive { public static void main(String[] args) { // ArrayList的特点:底层使用可变长度数组实现 // ArrayList频繁存取的效率低,遍历效率高 List list = new ArrayList(); // 在第一次调用add方法时给数组初始化长度,初始化长度为10。 // 当元素数超过数组长度时扩容,按照原来长度的1.5倍扩容 list.add("Tom"); List list1 = new Vector(); } }
LinkedList
public class TestSix { public static void main(String[] args) { // LinkedList底层使用双向链表实现,LinkedList频繁存取的效率高,遍历效率低 // LinkedList有一套对首尾元素单独操作的方法 LinkedList list = new LinkedList(); list.add("Mary"); list.addFirst("Tom"); list.addLast("Jerry"); list.removeFirst(); list.removeLast(); list.getFirst(); list.getLast(); } }
Vector
三者区别
1、请描述ArrayList和LinkedList的主要区别。 .ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。 // ArrayList的特点:底层使用可变长度数组实现 // ArrayList频繁存取的效率低,遍历效率高 / 在第一次调用add方法时给数组初始化长度,初始化长度为10。 // 当元素数超过数组长度时扩容,按照原来长度的1.5倍扩容 // LinkedList:底层使用双向链表实现,LinkedList频繁存取的效率高,遍历效率低 // LinkedList有一套对首尾元素单独操作的方法 Vector:是线程安全的动态数组,底层是数组结构,初始化为长度为10的数组,如果容量满了,按照2.0倍扩容。除了支持foreach和Iterator遍历,还支持Enumeration迭代 2、请列举出至少五个Collection的常用方法 collection col = new Arraylist col.add();参数都是Object类型, col.addAll(); col.remove(); col.clear(); col.size(); toArray();将集合转成数组 iterator返回迭代器 3、请写出代码,创建一个List的集合对象, 并尝试向集合中添加若干元素,并使用迭代器遍历集合。 普通for循环 List list = new Arraylist list.add("Tom"); list.add("Jeck"); list.add("Marry"); list.add("Alex"); list.add("Mark"); for(int i = 0;list.size();i++){ 强转 String string =(String)list.get(i); sout(string); } Iterator iterator =list.iterator();//返回迭代器 while(Iterator.hasNext()){ String s = (String)interator.next;返回的任然是object类型 sout(s); } for(Object o ; list){ String s = (String)o sout(s); }
Set接口
Set接口: 无下标,无序(新增顺序和遍历顺序不一致); 不允许重复记录(去重); 没有独有的方法 HasSet的底层 Set set = new HashSet;
HashSet

LinkedHashSet
二者hashCode和equals 区别元素是否相等
TreeSet
自然排序
// 自然排序:需要对象比较大小则需要类实现Comparable接口 public class Student implements Comparable{ private String stuName; private int stuAge; private String stuGender; public Student() { } public Student(String stuName, int stuAge, String stuGender) { this.stuName = stuName; this.stuAge = stuAge; this.stuGender = stuGender; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public int getStuAge() { return stuAge; } public void setStuAge(int stuAge) { this.stuAge = stuAge; } public String getStuGender() { return stuGender; } public void setStuGender(String stuGender) { this.stuGender = stuGender; } @Override public String toString() { return "Student{" + "stuName='" + stuName + '\'' + ", stuAge=" + stuAge + ", stuGender='" + stuGender + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Student)) return false; Student student = (Student) o; return getStuAge() == student.getStuAge() && getStuName().equals(student.getStuName()) && getStuGender().equals(student.getStuGender()); } @Override public int hashCode() { return Objects.hash(getStuName(), getStuAge(), getStuGender()); } // 如果方法返回负数则代表调用方法的对象小,参数对象大 // 如果方法返回正数则代表调用方法的对象大,参数对象小 // 返回0代表两个对象相等 @Override public int compareTo(Object o) { Student stu = (Student)o; // return this.getStuAge() - stu.getStuAge();// 升序排列 // return stu.getStuAge() - this.getStuAge();// 降序排列 int result = this.getStuAge() - stu.getStuAge(); if(result == 0){ result = this.getStuName().compareTo(stu.getStuName()); } if(result == 0){ result = this.getStuGender().compareTo(stu.getStuGender()); } return result; } } ---------------------------------------------------------------- public class TestFour { public static void main(String[] args) { // TreeSet底层使用红黑树实现 // 如果放入TreeSet集合中的元素使用实现Comparable接口的方式比较大小,则这种方式被称作自然排序 Set set = new TreeSet(); // set.add("Tom"); // set.add("Jerry"); // set.add("Mary"); // set.add("Jane"); Student stu = new Student("Tom",20,"男"); Student stu1 = new Student("Jerry",23,"男"); Student stu2 = new Student("Mary",24,"女"); Student stu3 = new Student("June",24,"女"); set.add(stu); set.add(stu1); set.add(stu2); set.add(stu3); for (Object o : set) { System.out.println(o); } } }
定制排序
public class Student private String stuName; private int stuAge; private String stuGender; public Student() { } public Student(String stuName, int stuAge, String stuGender) { this.stuName = stuName; this.stuAge = stuAge; this.stuGender = stuGender; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public int getStuAge() { return stuAge; } public void setStuAge(int stuAge) { this.stuAge = stuAge; } public String getStuGender() { return stuGender; } public void setStuGender(String stuGender) { this.stuGender = stuGender; } @Override public String toString() { return "Student{" + "stuName='" + stuName + '\'' + ", stuAge=" + stuAge + ", stuGender='" + stuGender + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Student)) return false; Student student = (Student) o; return getStuAge() == student.getStuAge() && getStuName().equals(student.getStuName()) && getStuGender().equals(student.getStuGender()); } @Override public int hashCode() { return Objects.hash(getStuName(), getStuAge(), getStuGender()); } --------------------------------------------------------------- public class TestFive { public static void main(String[] args) { // 定制排序,定制排序优先级更高 Set set = new TreeSet(new Comparator(){ // 如果方法返回负数则代表第一个参数小,第二个参数大 // 如果方法返回正数则代表第一个参数大,第二个参数小 // 如果返回0则代表两个参数相等 @Override public int compare(Object o1, Object o2) { Student stu1 = (Student)o1; Student stu2 = (Student)o2; int result = stu2.getStuAge() - stu1.getStuAge(); if(result == 0){ result = stu2.getStuName().compareTo(stu1.getStuName()); } if(result == 0){ result = stu2.getStuGender().compareTo(stu1.getStuGender()); } return result; } }); Student stu = new Student("Tom",20,"男"); Student stu1 = new Student("Jerry",23,"男"); Student stu2 = new Student("Mary",22,"女"); Student stu3 = new Student("June",24,"女"); set.add(stu); set.add(stu1); set.add(stu2); set.add(stu3); for (Object o : set) { System.out.println(o); } } }
Collections工具类
提供静态方法操作集合 public class TestSix { public static void main(String[] args) { // Collections工具类 Collection col = new ArrayList(); col.add("Tom"); col.add("Jerry"); System.out.println(col.size()); Collections.addAll(col,"xiaoming","xiaoqiang","sanmao"); System.out.println(col.size()); System.out.println(col); List list = new ArrayList(); list.addAll(col); Collections.sort(list);根据元素的自然顺序对指定 List 集合元素按升序排序 System.out.println(list); int index = Collections.binarySearch(list,"Jerry"); System.out.println(index); Collections.reverse(list);反转指定列表List中元素的顺序。 System.out.println(list); // Collections.shuffle(list);集合元素进行随机排序,类似洗牌 // System.out.println(list); Collections.swap(list,1,3);将指定 list 集合中的 i 处元素和 j 处元素进行交换 System.out.println(list); list.add("sanmao"); System.out.println(Collections.frequency(list, "sanmao")); System.out.println("--------------------------------------"); Collections.replaceAll(list,"xiaoming", "Alex"); System.out.println(list); } public static <T> void copy(List<? super T> dest,List<? extends T> src)将src中的内容复制到dest中 public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal):使用新值替换 List 对象的所有旧值 Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题 Collections类中提供了多个unmodifiableXxx()方法,该方法返回指定 Xxx的不可修改的视图。 }
Map接口
常见方法   --------------------------------------------------------------------- public static void main(String[] args) { Map map = new HashMap(); map.put("班长","美国");// 将元素存入map集合,前键后值 map.put("学委","中国"); map.put("体委","俄罗斯"); map.put("文委","意大利"); //遍历所有的键集 //map种的key是无序不可重复,使用set存储所有key, key所在的类需要重写equals和hashcode Set set = map.keySet(); Iterator iterator =set.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } //遍历所有的值集 //map中的value是无序可重复的使用collection存储所有的value Collection col = map.values(); Iterator iterator1 = col.iterator(); while(iterator1.hasNext()){ System.out.println(iterator1.next()); } System.out.println("----------------------"); Collection value = map.values(); for (Object o : value) { System.out.println(o); } //遍历键值对集 //map中的entry:无序不可重复使用Set存储所有的entry Set entrySet = map.entrySet(); Iterator iterator2 = entrySet.iterator(); while(iterator2.hasNext()){ //entrySet集合中的元素都是entry Object o = iterator2.next(); Map.Entry entry = (Map.Entry)o; System.out.println(entry.getKey()+"="+entry.getValue()); }
HashMap实现类
// HashMap底层使用一个链表数组的方式实现, 在第一次调用put方法时数组初始化 // 数组初始化长度为16.负载因子的初始值是0.75。 当元素数超过负载因子和长度乘积时扩容 // 按照原来长度的两倍扩容,扩容之后所有的元素重新计算存储位置。 // 从JDK1.8开始,如果集合中某个链表的元素数超过了8个 ,并且此时数组长度没有达到64位,则 // 数组扩容。如果超过64位了,则将原有的链表结构变成红黑树结构。 // 从jdk1.8开始,HashMap底层使用链表+数组+红黑树的形式存储数据 HashMap实现Map接口,它允许任何类型的键和值对象,并允许将null用作键或值
Hashable实现类
区别
  Hashtable是线程安全的哈希表,底层结构是数组+链表。 HashMap是线程不安全的哈希表,底层结构是JDK1.7时数组+链表,JDK1.8时数组+链表/红黑树。 HashMap的线程安全问题可以使用Collections的synchronizedMap(Map<K,V> m) 方法解决
TreeMap实现类
LinkedHashMap实现类
Properties实现类
泛型
为什么使用泛型    -------------------------------------------------------------------  Entry作为map的内部接口,使用时需要利用Map.Entry进行调用   ---------------------------------------------------------------------
在集合中使用泛型
 --------------------------------------------------------------------------------- 在自然排序中的使用   ----------------------------------------------------------------------------------- 编写代码实现List,Set,Map的泛型集合声明和使用 
网路编程20
客户端和服务器端的双向单次通讯 
网络通讯的概述和网络通讯的要素
TCP编程
UDP编程
基础的API和算法
Math类常用方法
// Math类的常用方法 double d1 = Math.ceil(-5.1);// 返回距离参数最近的比参数大的整数 System.out.println(d1); double d2 = Math.floor(-5.5);// 返回距离参数最近的比参数小的整数 System.out.println(d2); double d3 = Math.round(5.4);// 四舍五入的方式计算整数 System.out.println(d3); double max = Math.max(5.8,3.5);// 两个参数返回大的那个 System.out.println(max); int min = Math.min(5,7);// 两个参数返回小的那个 System.out.println(min); Math.random(); Math类方法和属性都是静态,没有构造方法,直接由类名进行调用 Date类 LocalDate localDate = LocalDate.now();// 没有时间的日期格式 System.out.println(localDate); System.out.println(localDate.getYear()); System.out.println(localDate.getMonth().getValue()); System.out.println(localDate.getDayOfMonth()); System.out.println(localDate.getDayOfWeek().getValue()); System.out.println("---------------------------------------"); LocalTime localTime = LocalTime.now();// 没有日期的时间格式 System.out.println(localTime); System.out.println(localTime.getHour()); System.out.println(localTime.getMinute()); System.out.println(localTime.getSecond()); System.out.println(localTime.getNano()); System.out.println("------------------------------------------"); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDateTime);
数组的算法
数组的反转 1声明新数组,遍历转换,再将新数组赋值给原数组  2或则直接遍历条件为int i = 0,i < nums.length / 2;i++ !引入变量进行交换  数组的扩容 方式1: int[] nums = {54,86,90,77,29,67}; int[] newNums = new int[nums.length*2]; 方式2: int[] newNums = Arrays.copyOf(nums,nums.length*2); 数组元素的插入 指定向第一个空位 声明需要插入的变量 声明索引,遍历 !!找到索引结尾break,if判断再for外 if循环判断遍历有空值和无空值。 指定数组索引进行插队 声明需要插入指定位置的变量 例如: int index = 2; int one = 101; 声明索引,遍历数组找出第一个为空值的下标 for(int i = emptyIndex;i > index;i--){//往后 nums[i] = nums[i - 1]; }将前面一个值赋给后一个 将指定值赋值给放在声明的最开始需要插入的位置 数组元素的删除 思路:定义需要删除的下标位置,找到第一个空位的小标 从需要删除的位置开始,第一个空值位置结束开始向前赋值 找指定元素的下标 先排序 在哪找,找谁,利用二分方法binarySearch()  数组的直接选择排序(冒泡排序)  二分法查找 定义数组 声明需要查找的元素 定义索引 int left = 0; int right = arr.length - 1; int mid = (left + right)/2; 定义whlie循环()条件为left<=right,内部嵌套if-else
String常用算法
// String的常用方法 String中常用方法有 charAt返回指定下标处 concat拼接字符串 endswith检查是否以..结尾 starstwith检查是否以..开始 equals考虑大小写的判断两个字符串串值是否相等 equalsIngorance忽略大小写的判断两个字符串串值是否相等 toUpperCase toLowerCase getByte将一个字符串拆解成字节数组 toCharArray将一个字符串拆解成char型数组 indexOf在调用方法的字符串中搜索参数字符第一次出现的索引  String word = "hello"; char c = word.charAt(1);// 返回指定下标处的字符 System.out.println(c); word = word.concat(" world");// 将参数字符串和调用方法的字符串拼接在一起 System.out.println(word); System.out.println(word.endsWith("dl"));// 判断调用方法的字符串是否以参数字符串结尾 System.out.println(word.startsWith("hel"));// 判断调用方法的字符串是否以参数字符串开头 System.out.println(word.equals("Hello world")); // 考虑大小写的判断两个字符串串值是否相等 System.out.println(word.equalsIgnoreCase("Hello World")); // 忽略大小写的判断两个字符串串值是否相等 System.out.println(word.toUpperCase().equals("Hello World".toUpperCase())); System.out.println(word.toLowerCase()); byte[] bs = word.getBytes();// 将一个字符串拆解成字节数组 char[] cs = word.toCharArray();// 将一个字符串拆解成char型数组 System.out.println(bs); System.out.println(cs); System.out.println("-------------------------------------------------"); System.out.println(word); int index1 = word.indexOf('l');// 在调用方法的字符串中搜索参数字符第一次出现的索引 System.out.println(index1); System.out.println(word.indexOf('l', word.indexOf('l')+1));// 在调用方法的字符串中从第二个参数索引位置开始搜索第一个参数字符第一次出现的索引 int index2 = word.indexOf("ll");// 在调用方法的字符串中搜索第一个参数字符串出现的索引位置 System.out.println(index2); word.indexOf("ll",2); int index3 = word.lastIndexOf(97);// 如果找不到参数字符或者字符串则返回-1 System.out.println(index3); System.out.println(word.lastIndexOf("l", 8)); ----------------------------------------------------------------------------------- String两种不同的创建对象的方式的区别  这种方法创建字符串后会有一个字符串池来保存内容,而栈空间存的是这个字符串的地址。这种方法创建的字符串在作为函数参数时是值传递。  但是这种方法创建的字符串在传递时是引用传递。本应传递引用,但String 是不可变对象,所以在其值创建后,无法对其值做修改,所以跟值传递一个效果。  ------------------------------------------------  请解释String、StringBuilder、StringBuffer的区别? 1String是不可变的字符序列,因此字符串常量存储在常量池中, String对象是常量对象,因此一旦拼接和修改就会产生新的String对象。 而StringBuilder和StringBuffer是可变的字符序列。 SringBuffer和StringBuilder可以在原对象上进行append,insert,delete,replace等修改。 StringBuilder和StringBuffer是完全兼容的API, 但是StringBuilder是线程不安全的 、StringBuffer是线程安全的。
多线程
java语言中的两种 开启子线程的方式
第一种开启子线程的方法  测试  假设创建对象后直接调用方法run则和调用方法methodOne没有区别 ----------------------------------------------------------- 第二种开启子线程的方式:实现Runnable接口  thread类也是实现Runnable接口 测试 !实现的接口runnable当中只有run方法,所以不能直接调用start开启 所以需要方法需要找有方法的类 当创建线程对象时,传递了一个runnable的对象,则开启的子线程调用参数的run方法  开启多个需创建多个对象 -----------------------------------------------------------
线程类的常用方法
// getName()获取当前线程的线程名 //如果类直接继承自thread类,则直接对象.getName即可, 如果没有关系获取当前线程对象.getName public Thread(String name) :分配一个指定名字的新的线程对象。 提供构造方法给子线程传参  
线程安全问题
package com.atguigu.test1; public class SellTicketThree implements Runnable{ private int tickets = 100;//静态属性不随着对象的加载而加载,随着类的加载而加载 private Object lock = new Object(); @Override public void run() { while(true){ try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } // synchronized (lock) {//同步锁位置对象要唯一,创建唯一对象即可。 // synchronized ("lock") { // synchronized (this){ synchronized (SellTicketThree.class){ if (tickets <= 0) { System.out.println("票以售完!!!!!!!!!!!"); break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "线程卖出一张票,当前剩余票" + (--tickets) + "张~~~~~~~~~~~~~"); } } } } --------------------------------------------------------------------------------------------public class TestTwo { public static void main(String[] args) { SellTicketTwo stt1 = new SellTicketTwo(); SellTicketTwo stt2 = new SellTicketTwo(); SellTicketTwo stt3 = new SellTicketTwo(); stt1.start(); stt2.start(); stt3.start(); } }
线程中的通讯问题
单个生产和消费
创建库存类Stone 声明属性item 声明两个方法Add,get 方法体: if循环内满足条件打印→this.wait Thread.sleep sout打印 this.notify ----------------------------------------------------------------- 创建生产和消费 写成死循环 重写的方法需要get方法,但是该方法是重写的,而且父类也没有形参,所以将Stone做成属性,提供构造方法将其类中的方法调用 ----------------------------------------------------------------- 
多个生产和消费
 单个→多个,if-改写成while执行完成之后继续返回判断