java基础【大爆炸】全面总结
文章目录
- Day1
-
-
- hello world
- JAVA面试题 自增自减
- java输入操作相关
- java 负小数取模细节
- 字符串转数字的方法 Integer.parseInt()
-
- Day2
-
-
- 字符串转字符和获取字符的方法
- switch细节
- 输入类创建的细节
-
- Day3
-
-
- break的细节
- random随机数方法
- 字符串比较
- 数组动态开辟的方法
- java 实现冒泡排序
- 数组创建易错点
-
- Day4
-
-
- 数组的赋值机构,引用/地址传递
- 数组细节垃圾回收
- 数组扩容
- 数组缩容
- 二维数组的元素个数组求法
- 二维数组开辟空间细节
- 二维数组练习题
- 二维数组练习题
-
- Day5
-
-
- 有序数组插入一个数字
- 类和对象,创建一个类和对象
- 对象的内存分布
- 方法的快速入门
- 方法的内存调用机制
- 方法的细节
- 方法传参机制,地址传参
-
- Day6
-
-
- 完成拷贝功能
- 递归完成猴子吃桃问题
- 小老鼠走迷宫问题
- 汉诺塔
- 可变参数
-
- Day7
-
-
- 作用域
- 作用域细节
- 作用域引用细节
- 构造器
- 无参构造器
- 对象引用创建的分析
- this的引出
- this 的引用
-
- Day8
-
-
- this的介绍
- this 的细节
- 构造器细节
- this 的练习题,比较年龄和名字
- 练习题1寻找最大数 健壮性
- 匿名创建对象
- idea中文件的形成
- idea必需会的快捷键
- 提高速度的模板
- 猜拳游戏
-
- Day9
-
-
- 包的三大作用
- 包的命名
- 包的使用细节
- 访问修饰符
- 访问修饰符的作用
- 修饰符的注意事项
- 错误点
- 封装的好处
- 封装的实现步骤
-
- Day10
-
-
- 封装入门
- 封装与构造器
- 继承
- 继承的入门
- 继承的细节
-
- Day11
-
-
- 继承的本质
- 构造器练习题1
- 练习题2
- super 关键字
- super的细节
- this和super的区别
-
- Day12
-
-
- 方法的重写(覆盖)
- 细节1
- 重写练习题1《重写和重载的区别》
- 重写练习题2
-
- Day13
-
-
- 引出多态
- 对象的多态
- 多态的方法实现主人喂给动物食物
- 多态细节-向上转型
- 向下转型
- instanceof 比较操作符
- 多态练习1
- java 的动态绑定机制(非常非常重要.)
- 多态数组2
-
- Day14
-
-
- 多态参数
- ==详解
- JDK的源码---equals
- equals练习1
- equals练习2
- 初识hashCode
- toString
- finalize 方法
-
- Day15
-
-
- 断点调试
- 断点调试练习题
-
- Day16
-
-
- 零钱通程序,面向过程版
- 零钱通OOP版
- 练习题1
- 练习题2
- 练习题3
- 练习题4
- 练习题5
- 练习题7
- 练习题8
- 练习题9
- 练习题10*
- 练习题11 ==和equals的区别
- 练习题12*
- 练习题13
-
- Day17
-
-
- 房屋出租系统
- 代码实现
-
- Day18面向对象高级部分
-
-
- 静态变量的内存布局
- 类变量的定义与使用
- 类变量细节
- 静态方法 模拟学生缴费
- 静态方法的实例
- 静态方法的细节
- 理解main方法语法
- main的动态传参
-
- Day19
-
-
- 代码块入门
- 代码块细节1
- 代码块细节2
- 代码块细节3
- 代码块细节4(面试题)
- 代码块练习
-
- Day20
-
-
- 单例模式饿汉式
- 懒汉式
- final关键字
- final细节2
- 抽象类
- 模板设计模式
-
- Day21
-
-
- 接口入门
- 接口的具体应用场景
- 接口的细节
- 接口VS继承
- 接口的多态
- 接口数组
- 接口的多态传递
-
- Day22
-
-
- 内部类快速入门
- 局部内部类
- 匿名内部类本质
- 匿名内部类的细节
- 匿名内部类的应用场景
- 成员内部类的细节
- 静态内部类
-
- Day23
-
-
- 自定义枚举类
- enum 关键字实现枚举-快速入门
- enum常用方法&增强for循环
- enum实现接口
- 注解
- 匿名内部类练习题
- 匿名内部类练习题
- 交通方式题*
- 枚举练习题
-
- Day24
-
-
- 异常
- 异常介绍
- 五大常见异常
- 编译时异常
- 异常处理
- try-catch异常处理
- 异常练习题
- try-catch最佳实践 无限输入判断是不是整数
- throws 异常处理
- throws异常细节
- 自定义异常
- 异常练习题1
-
- Day 25
-
-
- 包装类
- 拆箱与装箱
- 练习题
- StringInteger 转换方式
- integer面试题
- String类
- 创建 String 对象的两种方式
- 测试题
- String 类的常见方法一览
- StringBuffer 类
- String VS StringBuffer
- String 和 StringBuffer 相互转换
- StringBuffer 类常见方法【增删查改】
- StringBuffer 类课堂测试题1
- StringBuffer 类课堂测试题2
- StringBuilder 类
- String、 StringBuffer 和 StringBuilder 的比较
- Math八大常用方法(含求a-b之间的随机数)
-
Day1
hello world
public class hello{//严格记住大小写,java操作时 直接java hello(类)//public static void main(String[] args){System.out.println("hello world~");}}
JAVA面试题 自增自减
以上是C语言的
java是先把i的值暂存起来在对,i++,最后再把暂存的赋給i
java输入操作相关
import java.util.Scanner;//导入java util 下面的类 和包含头文件差不多public class Var03{public static void main(String[] args){ //创建一个Scanner的输入类 //new:创建的意思 Scanner My_Scanner = new Scanner(System.in); System.out.println("请输入名字:"); String name=My_Scanner.next();//单独的next是输入字符串 System.out.println("请输入年龄:"); int age=My_Scanner.nextInt();//输入int类型的值返回到int 类型的变量 System.out.println("请输入薪资:"); double salary=My_Scanner.nextDouble(); System.out.println("名字:"+name+"\t年龄:"+age+"\t薪资:"+salary);}}
java 负小数取模细节
System.out.println(-10.5%3);//-1.5是近似值// 公式:-10.5-((int)-10.5)/3*3=-10.5-(-3*3)=-10.5+9=-1.5// 注意再C中小数不能取模,java可以,但是运算是隐式转换 // 为整数运算
字符串转数字的方法 Integer.parseInt()
// 字符串转为数字的方法 int swit_num = Integer.parseInt("123"); System.out.println(swit_num); double num_1 = Double.parseDouble("123"); float num_2 = Float.parseFloat("303.03"); System.out.println(num_2); System.out.println(num_1);}
Day2
字符串转字符和获取字符的方法
String str2 = "123"; char ch = str2.charAt(1); System.out.println(ch); //字符串转换为字符方法: str2.charAt(n) 表示把字符串的第n个字符存到ch字符变量 char sex = My_Scanner.next().charAt(0); //上面这就话的解读:扫描一个字符串, .charSt(0) 获取该字符串的首个字符
switch细节
输入类创建的细节
Day3
break的细节
random随机数方法
int count = 0;for(int i=0;;i++){//math.random()表示返回一个0.0~1.0之间double类型的数字if((int)(Math.random()*100)==97)break;count++;}
字符串比较
import java.util.Scanner;public class test01{ public static void main(String[] args){ Scanner My_Scanner = new Scanner(System.in); int i=3; while(i>0){ System.out.println("请输入名字:"); String Str1 = My_Scanner.next(); System.out.println("请输入密码:"); String Str2 = My_Scanner.next(); //字符串比较 拿张三和Str1比较 if("张三".equals(Str1)&&"666".equals(Str2)) break; i--; System.out.println("密码或用户名错误,请重新输入:还有"+i+"次机会:"); } if(i>0) System.out.println("登陆成功赏你个大嘴巴子"); else System.out.println("请使用别的方法登录..."); }}
数组动态开辟的方法
//数组动态开辟方法1 int[] a = new int [5];//定义了一个数组a 开辟了5个int类型的空间 //数组动态开辟方法2 int b[];//先声明 再C中这样是不行的,因为默认为是定义数组, b = new int [5];//可以理解为 b指向了一个合法的空间,开辟了5个int类型的空间
java 实现冒泡排序
int a[]={1,3,5,7,9,2,4,6,8,10}; int i=0,j=0; for(i=0;i<a.length-1;i++){ for(j=0;j<a.length-1-i;j++){ if(a[j]>a[j+1]){ int tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; } } } for(i=0;i<a.length;i++){ System.out.print(" "+a[i]); }
数组名.length求的是数组元素个数
数组创建易错点
//char a[26] = {'A'}; 这是错误的语法 char a[]= new char[26];//只能这样创建 for(int i=0;i<26;i++){ a[i]=((char)('A'+i)); } for(int j=0;j<26;j++){ System.out.print(" "+a[j]); }
Day4
数组的赋值机构,引用/地址传递
数组细节垃圾回收
数组扩容
int a[]={1,2,3};int i=0; while(true){ //新建一个数组比原来的数组动态的一个 int a_new[]=new int[a.length+1]; System.out.println("爷您是否扩容数组:是输入Y,否输入N"); char ch = My_Scanner.next().charAt(0); if(ch=='Y'){ //把原来的数组元素都复制到临时数组 for(i=0;i<a.length;i++){ a_new[i]=a[i]; } System.out.println("请输入要扩容的数字"); a_new[a_new.length-1] = My_Scanner.nextInt(); a=a_new; System.out.println("爷,扩容成功"); } else if(ch=='N')break; else { System.out.println("输入错误请重新输入"); } } for(i=0;i<a.length;i++){ System.out.print(a[i]+" "); }
数组缩容
int i=0; int a[] = {1,2,3,4,5,6,7,8,9,10}; while(true){ //判断是否缩容 System.out.println("缩容输入Y 否输入 N"); char ch = My_Scanner.next().charAt(0); if(ch=='Y'){ //判断该数组还有几个元素 if(a.length==1){ System.out.println("该数组只有一个元素不能再减少了!!!"); break; } //开辟一个临时数组 int tmp [] =new int[a.length-1]; for(i=0;i<a.length-1;i++){ tmp[i] = a[i]; } a=tmp; System.out.println("缩容成功"); System.out.println("====缩容之后===="); //打印缩容之后的数组 for(i=0;i<a.length;i++){ System.out.print(a[i]+"\t"); } System.out.print('\n'); } else if(ch == 'N') break; else System.out.println("输入错误,重新输入"); }
二维数组的元素个数组求法
//二维数组的引用 // 数组名.length求的是二维数组有几个元素 // 数组名[i].length求的是二维数组的元素一维数组的元素个数 int a[][]={{1,2,3},{4,5,6},{7,8,9}}; int i,j; for(i=0;i<a.length;i++){ for(j=0;j<=i;j++){ int tmp = a[i][j]; a[i][j] = a[j][i]; a[j][i] = tmp; } } for(i=0;i<a.length;i++){ for(j=0;j<a[i].length;j++){ System.out.print(a[i][j]+" "); } System.out.println('\n'); }
二维数组开辟空间细节
int a[][]= new int[3][]; //这是给二维数组开辟了三个元素,没有没有给一维数组开劈元素,a[i]指向的 //是NULL int i=0,j=0; for(i=0;i<a.length;i++){ a[i]= new int[i+1]; //为每个一维数组开辟空间,返回一个地址值,a[i]来接收 // //赋值 for(j=0;j<a[i].length;j++){ a[i][j]=i+1; } } //打印 for(i=0;i<a.length;i++){ for(j=0;j<a[i].length;j++) { System.out.print(a[i][j]+"\t"); } System.out.println(); }
int a[2][3]={{1,2},{1,2,3}}; //合法,称为列数不等的二维数组
二维数组练习题
int [] a,b[];// 这样声明 b是一个二维数组 a是一个一维数组 int i=0,j=0; b= new int [2][1]; b[0][0]=1; a = new int [3]; a[1]=1;
二维数组练习题
String str1[] = new String[]{"abx","bcd","ert"}; String str1[] = new String[3]{"abx","bcd","ert"};//错
Day5
有序数组插入一个数字
int sum = 0,i=0,j=0,index=-1; int arr1[] = {1,4,7,9}; while(true){ System.out.println("爷是否插入数字?--是:y --否:n"); char ch = My_Scanner.next().charAt(0); if(ch=='y'){ System.out.println("请输入要插入的数字"); sum = My_Scanner.nextInt(); //寻找合适的插入位置 for(i=0;i<arr1.length;i++){ if(sum>=arr1[i]); else break; }//重点考虑是不是这个sum比最后一个还大 index = i;//保存下标 //扩充 int arr2[] = new int [arr1.length+1]; for(i=0,j=0;i<arr2.length;i++){ if(i!=index){//不等于这个标记的下标就把arr1的内容付过去arr2[i]=arr1[j++]; } else {arr2[i]=sum; } } arr1=arr2; System.out.println("插入成功"); System.out.println("======数组情况====="); for(i=0;i<arr1.length;i++){ System.out.print(arr1[i]+" "); } } else if(ch=='n'){ System.out.println("退出..."); break; } else { System.out.println("输入有误..."); } }
//随机生成10个整数,判断其中有没有8 并求最大值,平均值,最大值下标 int a[] = new int [10]; int i=0; //十个随机数存到数组 for(i=0;i<a.length;i++){ a[i] = (int)(Math.random()*100); } int flag = -1,total = 0,max = a[0], index_max=0; for(i=0;i<a.length;i++){ if(a[i]==8){ flag = i; } if(max<a[i]){ index_max=i; max=a[i]; } total+=a[i]; } System.out.println("=====数组情况====="); for(i=0;i<a.length;i++){ System.out.print(a[i]+" "); } System.out.println(); if(flag != -1){ System.out.println("找的了下标是:"+flag); } else System.out.println("没找到该元素"); System.out.println("最大值是:"+max+"\t最大值下标是:"+index_max+ "\t总和是:"+total+"\t平均值是:"+total/10.0);
类和对象,创建一个类和对象
public class object{public static void main(String[] args){ //创建一个对象也就是创建一只猫 //创建一个猫对象给cat1 Cat cat1 = new Cat(); cat1.age= 10; cat1.name = "小红"; cat1.weight = 90.8; Cat cat2 = new Cat(); cat2.age= 12; cat2.name = "小驴"; cat2.weight = 90.8; System.out.println("第一只猫:"+cat1.age+" "+cat1.name+" "+ cat1.weight); System.out.println("第一只猫:"+cat2.age+" "+cat2.name+" "+ cat2.weight);}}//创建一个猫类class Cat{int age;String name;Double weight;}
对象的内存分布
方法的快速入门
import java.util.Scanner;public class object{public static void main(String[] args){ Scanner My_Scanner = new Scanner(System.in); //用method类 创建了一个对象p Method p = new Method(); p.Speak();//调用成员方法 int n=0; System.out.println("请输入一个数字:"); n= My_Scanner.nextInt(); p.isshuNum(n);}}class Method{ //返回类型是void成员方法 public void Speak(){ System.out.println("you can see me..."); } //该成员方法是打印2~n之间的所有素数 public void isshuNum(int n){ int i=0,j; for(i=2;i<n;i++){ for(j=2;j<i;j++){ if(i%j==0)break; } if(j==i){ System.out.println(i); } } }}
方法的内存调用机制
方法的细节
细节一,返回多个值
import java.util.Scanner;public class object02{public static void main(String[] args){ Scanner My_Scanner = new Scanner(System.in); //用mathod类创建一个对象 mathod p = new mathod(); int[] ret=p.hle(10,20);//本质就是接收地址 System.out.println("调用返回相加结果是:"+ret[0]); System.out.println("调用返回相减结果是:"+ret[1]);}}class mathod{public int [] hle(int num1,int num2){int [] a=new int [2]; a[0] = num1+num2; a[1] = num1-num2; return a;//返回数组名也就是返回堆空间的地址}}
返回类型可以是任意类型,基本类型或引用类型(数组,对象)
方法传参机制,地址传参
Day6
完成拷贝功能
递归完成猴子吃桃问题
mathod ptr=new mathod(); int days = 1; int ret=ptr.houzi(days); if(ret != -1) System.out.println("桃子数:"+ret); else System.out.println("输入有误");} } class mathod{public int houzi(int days){ if(days==10){ return 1; } else if(days>=1&&days<=9){ return (houzi(days+1)+1)*2; //前一天的桃子数+1乘2 等于后一天的}else{ System.out.println("输入有误"); return -1;} } }
小老鼠走迷宫问题
import java.util.Scanner;public class MiGong{public static void main(String[] args){Scanner My_Scanner = new Scanner(System.in);int map[][] = new int [8][7];int i=0,j=0;//最右边和最左边列上,赋值为1,1是障碍物for(i=0;i<8;i++){map[i][0] = 1;map[i][6] = 1;}//最上边和最下边的行上,赋值为1for(i=0;i<7;i++){map[0][i]=1;map[7][i]=1;}//障碍物的实现map[3][1] = 1;map[3][2] = 1;// map[2][1] = 1;// map[2][2] = 1;// map[1][2] = 1;mathod ptr = new mathod();ptr.Print(map);ptr.findway(map,1,1);System.out.println("=====操作完之后=====");ptr.Print(map);}}class mathod{// 打印方法public void Print(int tmp[][]){int i=0,j=0;for(i=0;i<tmp.length;i++){for(j=0;j<tmp[i].length;j++){System.out.print(tmp[i][j]+" ");}System.out.println();}}// 寻找出路// 1:障碍物 2 :通路 3 :死路public boolean findway(int map[][],int i,int j){if(map[6][5]==2){//说明找到了出口return true;}//找出口的顺序是: 下-->右-->上-->左else if(map[i][j]==0){map[i][j] = 2;//把该位置假设为是通路if(findway(map,i+1,j)){//先往下边找 return true;} else if(findway(map,i,j+1)){//往右边找return true;}else if(findway(map,i-1,j)){//往上面找return true;}else if(findway(map,i,j-1)){//往左边找return true;}else {map[i][j]= 3;return false;}}else {//以上条件全不满足就退出return false;}}}
汉诺塔
import java.util.Scanner;public class MiGong{public static void main(String[] args){Scanner My_Scanner = new Scanner(System.in);mathod ptr = new mathod();System.out.println("请输入有多少个盘子");int num =My_Scanner.nextInt();ptr.hannoTa(num,'A','B','C');}}class mathod{public void hannoTa(int num,char a,char b,char c){if(num==1){//如果挪到了最后一个就挪到c塔System.out.println(a+"->"+c);}else {//把超过1个盘的我们看作两份,先挪num-1个到b塔//调用一次挪一个盘子 num-1 ,借助c塔挪到b塔hannoTa(num-1,a,c,b); //完事之后把最下面的挪到cSystem.out.println(a+"->"+c);//再把b塔的所有盘挪到c,借助ahannoTa(num-1,b,a,c);}}}
可变参数
import java.util.Scanner;public class MiGong{public static void main(String[] args){Scanner My_Scanner = new Scanner(System.in); Kebian ptr = new Kebian(); ptr.deal(1,2,3,4,5,6);}}/* 可变参数 必须是在最后面 函数形参里面只能有一个 nums可以当作数组使用 实参个数可以是0~多 */class Kebian{//public void deal(int...nums){for(int i=0;i<nums.length;i++){System.out.print(nums[i]+" ");}}}
import java.util.Scanner;public class MiGong{public static void main(String[] args){Scanner My_Scanner = new Scanner(System.in); Kebian ptr = new Kebian(); System.out.println(ptr.deal("张三",1,2)); System.out.println(ptr.deal("李四",1,2,3,4));}}class Kebian{//细节返回字符串public String deal(String str1,int...nums){int total = 0;for(int i=0;i<nums.length;i++){total+=nums[i];}return "名字"+str1+"总成绩"+total+" ";}}
Day7
作用域
作用域细节
作用域引用细节
import java.util.Scanner;public class MiGong{public static void main(String[] args){Scanner My_Scanner = new Scanner(System.in); //方法1:创建一个新的类,来间接调用 Test ptr = new Test(); ptr.aaa(); //方法2 Kebian prc = new Kebian(); ptr.bbb(prc);//直接传递类名 }}class Test{Kebian ptr = new Kebian();//全局变量可以通过成员方法的调用,在别的类里面来使用public void aaa(){ System.out.println(ptr.num);}//直接传类名(类的地址)来访问 p类的成员public void bbb(Kebian p){System.out.println(p.num);}}class Kebian{int num= 123;}
全局变量可以用修饰符,局部变量不能用修饰符
构造器
- 构造器的修饰符可以默认, 也可以是 public protected private
- 构造器没有返回值
- 方法名 和类名字必须一样
- 参数列表 和 成员方法一样的规则
- 构造器的调用, 由系统完成
构造器
import java.util.Scanner;public class MiGong{public static void main(String[] args){Scanner My_Scanner = new Scanner(System.in);//当我们在创建一个对象是直接通过构造器指定年龄和名字person ptr = new person("张三",20);//}}/* 构造器的名字必须和类名一致 不能有返回值 void也不行 形参必须和成员变量一致 */class person{int age;String name;public person(String Pname,int Page){System.out.println("构造器被调用...");age = Page;name = Pname;}}
构造器的重载
import java.util.Scanner;public class MiGong{public static void main(String[] args){Scanner My_Scanner = new Scanner(System.in);//当我们在创建一个对象是直接通过构造器指定年龄和名字person ptr = new person("张三",20);//person prc = new person("李四");System.out.println("名字"+ptr.name+"年龄"+ptr.age);System.out.println("名字"+prc.name+"年龄"+prc.age);}}/* 构造器的名字必须和类名一致 不能有返回值 void也不行 形参必须和成员变量一致 */class person{int age;String name;//构造器的重载public person(String Pname,int Page){System.out.println("构造器被调用...");age = Page;name = Pname;}public person(String Iname){System.out.println("构造器被调用11111");name = Iname;}}
无参构造器
对象引用创建的分析
this的引出
this 的引用
Day8
this的介绍
this 的细节
访问成员方法的语法
细节
this访问成员变量
构造器细节
this 的练习题,比较年龄和名字
import java.util.Scanner;public class test003{ public static void main(String[] args){ Scanner My_Scanner = new Scanner(System.in); //创建了两个构造器对象,赋的值都是一样的 person ttt = new person(12,"李四"); person buf = new person(12,"李四"); //用ttt对象和buf对象相比较 boolean ret = ttt.CompareTo(buf); if(ret==true){ System.out.println("信息完全对应..."); } else { System.out.println("信息不对应..."); } }}class person{int age;String name;public person(int age,String name){this.age = age;this.name = name;}public boolean CompareTo(person p){//this表示ttt对象的名字和年龄if(this.age==p.age&&this.name.equals(p.name)){return true;}else return false;}}
练习题1寻找最大数 健壮性
import java.util.Scanner;public class test004{ public static void main(String[] args){ Scanner My_Scanner = new Scanner(System.in); A01 ptr = new A01(); double a[] = {1.1,22.2,33.4,55,7.2,23}; Double ret = ptr.Max(a); if(ret!=null){ System.out.println("最大数是"+ret); } else { System.out.println("有错误!!!"); }}}//求最大数class A01{public Double Max(double a[]){//增加代码的健壮性,避免arr是null 避免arr长度为0if(a!=null&&a.length>0){int i=0;double max = a[0];for(i=1;i<a.length;i++){if(a[i]>max){max = a[i];}}return max;}else {return null;}}}
匿名创建对象
idea中文件的形成
idea必需会的快捷键
提高速度的模板
猜拳游戏
import java.util.Random;import java.util.Scanner;public class moraGame { public static void main(String[] args){ /* 请编写一个猜拳的游戏 有个人 Tom,设计他的成员变量. 成员方法, 可以电脑猜拳. 电脑每次都会随机生成 0, 1, 2 0 表示 石头 1 表示剪刀 2 表示 布 并要可以显示 Tom的输赢次数(清单), 假定 玩三次. */ //创建一个玩家对象 WanJia ptr = new WanJia(); int EndWinCount = 0;//记录最后赢得次数 //创建一个二维数组来存放 对局情况 int a[][] = new int[3][3]; //创建一个一维的字符串数组 String a1[] = new String[3]; Scanner My_scanner = new Scanner(System.in); int j=0,i=0; for( i=0;i<3;i++){ System.out.println("请输入:0--拳头,1--剪刀,2--布"); int num = My_scanner.nextInt();//输入数字 ptr.judge(num);//判断输入的数是否合法 //获得玩家输入的数字 int WanJia_num = ptr.GetWanJia_num(); //保存玩家输入的数字到二维数组 a[i][j+1] = WanJia_num; //获取电脑输入的数字放到二维数组 int ComputerNum = ptr.GetCom_Num(); a[i][j+2] = ComputerNum; //获取两个数的比较结果 String result = ptr.vscomputer(); a1[i] = result; a[i][j] = ptr.count;//记录第几局 //打印比赛情况 System.out.println("============================="); System.out.println("局数\t玩家出\t电脑出\t胜负情况"); System.out.println(a[i][j]+"\t "+a[i][j+1]+"\t "+a[i][j+2] +"\t "+result); System.out.println("=============================\n\n"); //获取人赢的次数 EndWinCount = ptr.EndWin_num(result); } //打印对局情况 System.out.println("局数\t玩家出\t电脑出\t胜负情况"); for(i=0;i<a.length;i++){ for(j=0;j<a[i].length;j++){ //内层打印对局情况 System.out.print(a[i][j]+"\t\t"); } System.out.print(a1[i]+"\t");//打印输赢情况 System.out.println(); } System.out.println("你赢了"+EndWinCount+"次\n"); }}class WanJia{ int WanJia_num; int com_num; int WinCount;//记录赢的次数 int count=1 ;//记录局数 //判断方法 public void judge(int num) { if (num > 2 || num < 0) { throw new IllegalArgumentException("数字输入错误"); } this.WanJia_num = num; }//返回玩家输入的数字 public int GetWanJia_num(){ return WanJia_num; } //返回电脑输入的数字 public int GetCom_Num(){ Random r; r = new Random(); //生成0-2的随机并存到成员变量中去 com_num = r.nextInt(3); return com_num; } //比较方法 public String vscomputer(){ if(WanJia_num==0&&com_num==1){ return "你赢了"; } else if(WanJia_num==1&&com_num==2){ return "你赢了"; } else if(WanJia_num==2&&com_num==0){ return "你赢了"; } else if(WanJia_num==com_num){ return "平局"; } else { return "电脑赢"; } } //获得最终赢的次数 public int EndWin_num(String tmp){ count++;//每次调用count++ 代表局数 if(tmp.equals("你赢了")){ WinCount++;//人赢的次数+1 } return WinCount; }}
Day9
包的三大作用
包的命名
包的使用细节
访问修饰符
访问修饰符的作用
即在一个包中不能使用,在一个类中行
修饰符的注意事项
错误点
类只能用public修饰和默认的修饰
封装的好处
封装的实现步骤
Day10
封装入门
package com.wpc01;import java.util.Scanner;public class fengzhuang { public static void main(String[] args) { Person person = new Person(); //设置属性 person.setName("张三李四王五马六"); person.setAge(300); person.setSalary(30000.0); person.Print(); }}class Person{ public String name; private int age; private double salary;//用快捷键 Alt+Enter 快捷生成 getxxx set xxx public String getName() { return name; } public void setName(String name) { //测试的业务逻辑 if(name.length()>=2&&name.length()<=6) { this.name = name; } else { System.out.println("名字长度有误,默认无名人"); this.name = "无名人"; } } public int getAge() { return age; } public void setAge(int age) {//增加相关逻辑,完善代码的合理 if(age<=130&&age>0){ this.age = age; } else { System.out.println("年龄输入错误,没有在1-130之间,赋默认值18"); this.age = 18; } } public double getSalary() { return salary; } public void setSalary(double salary) { System.out.println("请输入密码"); Scanner scanner = new Scanner(System.in); String str = scanner.next(); if(str.equals("123456")){ this.salary = salary; System.out.println("工资设置完毕"); } else{ System.out.println("密码错误,工资设置为0"); this.salary = 0; } } //打印方法 public void Print(){ System.out.println("名字="+name+" 年龄="+age+" 薪资="+salary); }}
封装与构造器
public Person(String name, int age, double salary) { //要想封装的业务逻辑构造器也能用,在构造器中直接调用方法 //在构造器中调用该person类的方法测试数据的合法性 setName(name); setAge(age); setSalary(salary); }
在构造器中调用方法,这样就可以测试数据的合理性了
继承
继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中
抽象出父类,在父类中定义这些相同的属性和方法, 所有的子类不需要重新定义这些属性和方法, 只需要通过 extends 来
声明继承父类即可
继承的入门
package com.wpc01.extends01;public class Testextends { public static void main(String[] args) { //调用子类里面的方法 Pupil pupil = new Pupil(); //Pupil 已经继承了父类的属性,给其子类的属性赋值 pupil.name = "花和尚"; pupil.age = 23; pupil.score = 89; pupil.Print(); pupil.Printf(); //Graduate 已经继承了父类的属性,给其子类的属性赋值 Graduate graduate = new Graduate(); graduate.name = "九纹龙"; graduate.age = 24; graduate.score = 99; graduate.Print(); graduate.Printf(); }}package com.wpc01.extends01;//父类,公用的代码public class Student { String name; int age; double score; public void Printf(){ System.out.println("大家好,hello world..."); }}package com.wpc01.extends01;//让子类 Pupil 继承 父类Student的属性public class Pupil extends Student { public void Print(){ System.out.println("小学生:"+name+" 年龄:"+age+" 分数:"+score); }}package com.wpc01.extends01;//让子类 Graduate 继承 父类Student的属性public class Graduate extends Student { public void Print(){ System.out.println("大学生:"+name+" 年龄:"+age+" 分数:"+score); }}
继承的细节
1) 子类继承了所有的属性和方法, 非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问, 要通过父类提供公共的方法去访问
package com.wpc01.extends02;public class RunExtends { public static void main(String[] args) { ExtendsTest extendsTest = new ExtendsTest(); extendsTest.Say01(); extendsTest.testN1();//子类调用父类的方法 extendsTest.testN2(); extendsTest.testN3(); extendsTest.Deal();//私有的方法不能直接调用可以间接调用 }}package com.wpc01.extends02;//子类继承了父类的属性和方法public class ExtendsTest extends Extendsdetail { public void Say01(){ Extendsdetail extendsdetail = new Extendsdetail(); System.out.println("n1="+extendsdetail.n1+" n2="+ extendsdetail.n2+" n3=" + extendsdetail.n3+" n4="+GetN4()); }}package com.wpc01.extends02;//父类public class Extendsdetail { public int n1 = 100; protected int n2 = 200; int n3 = 300; private int n4 = 400; public void testN1(){ System.out.println(n1); } protected void testN2(){ System.out.println(n2); }void testN3(){ System.out.println(n3); } private void testN4(){ System.out.println(n4); } public int GetN4(){ return n4; } public void Deal(){ testN4(); }}
2) 子类必须调用父类的构造器, 完成父类的初始化
3) 当创建子类对象时, 不管使用子类的哪个构造器, 默认情况下总会去调用父类的无参构造器, 如果父类没有提供无参构造器, 则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,
如果父类没有提供无参构造器, 则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作
4) 如果希望指定去调用父类的某个构造器, 则显式的调用一下 : super(参数列表)
5) super 在使用时, 必须放在构造器第一行(super 只能在构造器中使用)
6) super() 和 this() 都只能放在构造器第一行, 因此这两个方法不能共存在一个构造器
7) java 所有类都是 Object 类的子类, Object 是所有类的基类.
8) 父类构造器的调用不限于直接父类! 将一直往上追溯直到 Object 类(顶级父类)
9) 子类最多只能继承一个父类(指直接继承), 即 java 中是单继承机制。
思考: 如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】
10) 不能滥用继承, 子类和父类之间必须满足 is-a 的逻辑关系
Day11
继承的本质
如果找到的是private修饰的,不能再类之间使用会报错,父类还有该变量也不会去访问,会直接报错
构造器练习题1
package com.wpc01.extends03;public class RunAB { public static void main(String[] args) { B b = new B(); }}package com.wpc01.extends03;public class B extends A{ B(){ //这有this super就没有了 this("Tom"); System.out.println("B()被调用"); } B(String name){ //这默认有一个super 默认去调用父类的构造器 System.out.println("B(String name)被调用"); }}package com.wpc01.extends03;public class A { A(){ System.out.println("a---"); } A(String name){ System.out.println("A(String name)被调用"); }}
练习题2
package com.test;public class Test1 { public static void main(String[] args) { /* PC 是子类 构造器是有参的 */ PC pc = new PC("intel",512,"1T","华为"); pc.setBrand("华硕");pc.Getdetail(); System.out.println(pc.brand); NotePad notePad = new NotePad("小米",256,"256G","黄色"); notePad.Getdetail(); System.out.print(notePad.getColor()); }}package com.test;public class PC extends Computer { public String brand; public PC(String CPU, int memory, String disk, String brand) { //构造器是有参的,继承了父类的属性,super要显示一下因为父类是有参构造器 //这样父类直接可以赋值 super(CPU, memory, disk); this.brand = brand; }package com.test;public class NotePad extends Computer { private String color; public NotePad(String CPU, int memory, String disk, String color) { super(CPU, memory, disk); this.color = color; } public String getColor() { return color; } public void setColor(String color) { this.color = color; }}package com.test;import sun.plugin2.gluegen.runtime.CPU;public class Computer { private String CPU; private int memory; private String disk; public Computer(String CPU, int memory, String disk) { this.CPU = CPU; this.memory = memory; this.disk = disk; } public void Getdetail(){ System.out.println("CPU "+CPU+"\t内存 "+memory+"\t硬盘 "+disk); }}
案例 2ExtendsExercise02.java
编写 Computer 类, 包含 CPU、 内存、 硬盘等属性, getDetails 方法用于返回 Computer 的详细信息
编写 PC 子类, 继承 Computer 类, 添加特有属性【品牌 brand】
编写 NotePad 子类, 继承 Computer 类, 添加特有属性【color】
编写 Test 类, 在 main 方法中创建 PC 和 NotePad 对象, 分别给对象中特有的属性赋值, 以及从 Computer 类继承的
属性赋值, 并使用方法并打印输出信息
super 关键字
super 代表父类的引用, 用于访问父类的属性、 方法、 构造器
super的细节
//找 cal 方法时(cal() 和 this.cal()), 顺序是:
// (1)先找本类, 如果有, 则调用
// (2)如果没有, 则找父类(如果有, 并可以调用, 则调用)
// (3)如果父类没有, 则继续找父类的父类,整个规则, 就是一样的,直到 Object 类
// 提示: 如果查找方法的过程中, 找到了, 但是不能访问, 则报错, cannot access
// 如果查找方法的过程中, 没有找到, 则提示方法不存在
//cal();
this.cal(); //等价 cal
//找 cal 方法(super.call()) 的顺序是直接查找父类, 其他的规则一样
//super.cal()
this和super的区别
Day12
方法的重写(覆盖)
细节1
重写练习题1《重写和重载的区别》
重写和重载的区别
重写练习题2
1) 编写一个 Person 类, 包括属性/private(name、 age) , 构造器、 方法 say(返回自我介绍的字符串) 。
2) 编写一个 Student 类, 继承 Person 类, 增加 id、 score 属性/private, 以及构造器, 定义 say 方法(返回自我介绍的信息)。
3) 在 main 中,分别创建 Person 和 Student 对象, 调用 say 方法输出自我介绍
```cpackage pratice;public class test02 { public static void main(String[] args) { Student student = new Student("张三",21,1,90); System.out.println(student.Say()); }}package pratice;public class Student extends Person { private int id; private double score; public Student(String name, int age,int id ,double score) { super(name, age);//再形成子类之前去调用父类,完成父类的初始化 this.id=id; this.score=score; } public String Say(){//super的复用,在子类的成员方法中去调用父类的成员方法,在进行返回 return super.Say()+"学号: "+id+"成绩:"+score; }}package pratice;public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String Say(){ return "名字:"+name+"年龄: "+age; }}
Day13
引出多态
package com.test;public class Ploy_test { public static void main(String[] args) { A a = new A(); B b = new B(); //方法的重载 本类之间 a.Show(1, 2); a.Show(1, 2, 3); //方法的重写 父类和子类之间 a.Say(); b.Say(); }}package com.test;public class A extends B { public A() { System.out.println("A类构造器被调用。。。"); }//方法的重载 public void Show(int n1, int n2) { System.out.println(n1 + n2); } public void Show(int n1, int n2, int n3) { System.out.println(n1 + n2 + n3); } //这一个就是方法的重写,是发生在子类和父类之间的,返回类型是要和父类一样 //或者是父类返回类型的子类 子类方法不能缩小父类方法的访问范围 public void Say() { System.out.println("A类方法被调用..."); }}package com.test;public class B { public B() { System.out.println("B类构造器被调用..."); } public void Say() { System.out.println("B类的方法被调用...."); }}
方法的重写和重载就是多态的体现
对象的多态
package com.test;public class Ploy_test1 { public static void main(String[] args) { //animal 编译类型是Animal是不能改变的 //animal 运行类型是Dog是可以改变的 Animal animal=new Dog(); //父类的引用指向了子类的对象 //可以理解为:创建了一个Dog对象返回了Dog的地址, //放到了animal里面再引用Cry方法肯定是Dog里面的Cry方法 animal.Cry(); animal =new Cat(); //当前运行类型Cat,编译类型还是Animal animal.Cry(); }}public class Animal { //与子类构成了重写 public void Cry(){ System.out.println("Animal 叫叫..."); }}public class Dog extends Animal { //与父类构成了方法的重写 public void Cry(){ System.out.println("小狗叫...."); } public class Cat extends Animal { //与父类构成了方法的重写 public void Cry(){System.out.println("小猫叫..."); }}
多态的方法实现主人喂给动物食物
package com.Deal;public class Master { private String name; public Master(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } //使用多态就可以不用创建多个Feed方法了,直接传子类对象地址,用父类类型的引用来接收 //并且调用之 public void Feed(Animal animal,Fond fond){ System.out.println("主人 "+name+" 给 "+animal.getName()+" 喂 "+fond.getName()); }}package com.Deal;public class Fond { private String name; public Fond(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }}public class Animal { //这是父类 和子类有公共的属性name private String name; public Animal(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }}public class Dog extends Animal { //子类有用参构造器接收name public Dog(String name) { super(name);//父类无参构造器被覆盖要显示一下 }}public class Cat extends Animal{ public Cat(String name) { super(name); }}public class Feed { public static void main(String[] args) { Dog dog = new Dog("杀马特团长"); //返回一个运行类型为Dog的地址 //Dog是编译类型 Dog也是运行类型放到dog中 Bone bone = new Bone("好果汁"); //返回一个运行类型为Bone的地址放到bone中 //和上面同理 Master master = new Master("Fw"); //两个形参就是可以理解为是Dog类型的指针变量 把地址传给了父类引用,父类引用就可以 //调用子类的成员方法,bone同理 master.Feed(dog,bone); }}public class Bone extends Fond{ public Bone(String name) { super(name); }}
多态细节-向上转型
多态的前提是: 两个对象(类)存在继承关系,详细细节看代码
package com.Deal.Ploy;public class Ploy_Detail { public static void main(String[] args) { //向上转型: 父类的引用指向了子类的对象 //语法: 父类类型 引用名 = new 子类类型(); Animal animal = new Cat(); Object obj = new Cat();//可以吗? 可以 Object 也是 Cat 的父类 //向上转型调用方法的规则如下: //(1)可以调用父类中的所有成员(需遵守访问权限) //(2)但是不能调用子类的特有的成员 //(3)因为在编译阶段, 能调用哪些成员,是由编译类型来决定的 //animal.catchMouse();错误 //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时, 按照从子类(运行类型)开始查找方法 //, 然后调用 animal.eat();//猫吃鱼 因为子类个和父类构成了重写,当前运行类型是Cat,优先子类的 //没有再去父类找 // animal.catchMouse();这是不对的,catchMouse是子类特有的没有和父类构成重写 animal.run(); animal.show(); }}public class Animal { String name = "动物"; int age = 10; public void sleep(){ System.out.println("睡"); } public void run(){ System.out.println("跑"); } public void eat(){//与子类构成重写 System.out.println("吃"); } public void show(){ System.out.println("hello,你好"); } }public class Cat extends Animal{ public void eat(){//方法重写 //子类方法和父类方法重写才构成多态 System.out.println("猫吃鱼"); } public void catchMouse(){//Cat 特有方法 System.out.println("猫抓老鼠"); }}
向下转型
package com.Deal.Ploy;public class Ploy_Detail { public static void main(String[] args) { //向上转型: 父类的引用指向了子类的对象 //语法: 父类类型 引用名 = new 子类类型(); Animal animal = new Cat(); Object obj = new Cat();//可以吗? 可以 Object 也是 Cat 的父类 //向上转型调用方法的规则如下: //(1)可以调用父类中的所有成员(需遵守访问权限) //(2)但是不能调用子类的特有的成员 //(3)因为在编译阶段, 能调用哪些成员,是由编译类型来决定的 //animal.catchMouse();错误 //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时, 按照从子类(运行类型)开始查找方法 //, 然后调用 animal.eat();//猫吃鱼 因为子类个和父类构成了重写,当前运行类型是Cat,优先子类的 //没有再去父类找 // animal.catchMouse();这是不对的,catchMouse是子类特有的没有和父类构成重写 animal.run(); animal.show(); //多态的向下转型 //(1)语法: 子类类型 引用名 =(子类类型) 父类引用; //问一个问题? cat 的编译类型 Cat,运行类型是 Cat Cat cat = (Cat) animal; cat.catchMouse();//猫抓老鼠 //《只能强转父类的引用不能强转父类的对象》---对象就是在堆空间中开辟的空间,内容不能被强转 // 引用就是指针变量可以强转,只是把指针变量里面的值强转了,强转只是改变了我们如何看待那个地址 // (二进制序列),只是改变了类型 //(2)要求父类的引用必须指向的是当前目标类型的对象 Dog dog=(Dog)animal;//错误 当前animal是指向Cat这个对象的,强转为Dog类型是不对的 //Dog类型是指向狗类型对象的,不能指向Cat类型对象,animal能指向cat是因为animal是cat的 //父类 }}public class Cat extends Animal{ public void eat(){//方法重写 //子类方法和父类方法重写才构成多态 System.out.println("猫吃鱼"); } public void catchMouse(){//Cat 特有方法 System.out.println("猫抓老鼠"); }}public class Animal { String name = "动物"; int age = 10; public void sleep(){ System.out.println("睡"); } public void run(){ System.out.println("跑"); } public void eat(){//与子类构成重写 System.out.println("吃"); } public void show(){ System.out.println("hello,你好"); } }public class Dog extends Animal{}
instanceof 比较操作符
属性没有重写之说! 属性的值看编译类型
package com.Deal.Ploy; class method{ public static void main(String[] args) { base sub = new Sub(); // 属性没有重写之说! 属性的值看编译类型 System.out.println(sub.a);//30 Sub sub1 = new Sub(); System.out.println(sub1.a);//10 } } class Sub extends base{ int a=10;} class base{ int a=30;}
instanceOf 比较操作符, 用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型
package com.Deal.Ploy; class method{ public static void main(String[] args) { base sub = new Sub();// instanceOf 比较操作符, 用于判断对象的运行类型是否为 XX 类型// 或 XX 类型的子类型 System.out.println(sub instanceof Sub);//sub的运行类型就是Sub的所以返回true base sub1 = new Sub(); System.out.println(sub1 instanceof base);//sub1的运行类型是Sub 父类是base sub1运行类型是base的子类返回true base BB = new base(); System.out.println(BB instanceof Sub);//BB的运行类型不是Sub,sub也不是BB的父类所以返回false } } class Sub extends base{} class base{}
多态练习1
Object obj="hello world"; String str=(String)obj;//obj本就是字符串编译类型是Object,向下转型 Object obj1=new Integer(5); Integer str1=(Integer)obj1; //父类引用指向子类对象 在强转为子类型放到子类类型引用里面是没问题的 //integer是int的包装类也是Object的子类
java 的动态绑定机制(非常非常重要.)
package com.Deal.Ploy;import com.test.A;import com.test.B;public class Dt { public static void main(String[] args) {//a 的编译类型 A, 运行类型 B A1 a = new B1();//向上转型 //System.out.println(a.sum());// 40 //sum() 在B1类里面没有被注销时 调用方法要看运行类型 B1类里面有直接调用 System.out.println(a.sum());//30//sum()在子类B1里面注销之后,就去调用父类的sum()方法 //System.out.println(a.sum1());//30 //sum1() 在B1类里面没有被注销时 调用方法要看运行类型 B1类里面有直接调用 System.out.println(a.sum1());//20 }}class A1 {//父类 public int i = 10; //动态绑定机制: public int sum() {//父类 sum() return getI() + 10;//20 + 10 //调用该方法时,该方法会和该对象的内存地址(运行类型)绑定起来 //getI()就用到了动态绑定机制,子类和父类都有getI方法因为a.sum,a的运行对象 //是B1类型所以去调用B1里面的getI()方法,返回20 } public int sum1() {//父类 sum1() return i + 10;//10 + 10 }//B1里面的sum1方法被注销了,来调用A1里面的sum1(),注意i 这个i不是方法 //不会被绑定用的还是父类里面的i,所以时10+10 public int getI() {//父类 getI return i; }}class B1 extends A1 {//子类 public int i = 20; // public int sum() {// return i + 20;// } public int getI() {//子类 getI() return i; }// public int sum1() {// return i + 10;// }}
多态数组2
package com.Deal.Ploy;public class PloyArray { public static void main(String[] args) { Person [] persons=new Person[5]; //Person类型的数组 编译类型:Person persons [0]=new Person("张三",19); //运行类型是:Person persons [1]=new Student("李四",20,90); //运行类型是:Student persons [2]=new Student("王五",21,80); //运行类型是:Student persons [3]=new Teacher("歌姬",30,10000); //运行类型是:Teacher persons [4]=new Teacher("虎弟",29,20000); //运行类型是:Teacher for (int i = 0; i < persons.length; i++) { System.out.println(persons[i].Say()); //persons[i].Show();//这样是调用不了的,因为运行类型都不一样, //而Show方法在teacher里面和student里面有之后这两个运行类型的才能调用 //所以要强转 if(persons[i] instanceof Teacher){ //instanceof 判断目标运行类型是否为XX类型或XX类型的子类型 ((Teacher)persons[i]).Show(); } else if(persons[i] instanceof Student){ ((Student) persons[i]).Show(); } } }}package com.Deal.Ploy;public class Person { private String name; private int age; public Person(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; } public String Say(){ return name+"\t"+age; }}package com.Deal.Ploy;public class Student extends Person { private double score ; public Student(String name, int age,double score) { super(name, age); this.score=score; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } public String Say(){//和父类构成了重写 return "学生\t"+super.Say()+" " +score; } public void Show(){ System.out.println("学生: "+getName()+" 你来沈阳肯定没有你好果汁吃!!!"); }}package com.Deal.Ploy;public class Teacher extends Person { private double salary; public Teacher(String name, int age,double salary) { super(name, age); this.salary=salary; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } @Override public String Say() {//和父类构成了重写 return "老师 "+super.Say()+" "+salary; } public void Show(){ System.out.println("老师: "+getName()+"正在沈阳大街玩活!!!"); }}
Day14
多态参数
代码实现:
package com.Deal.PloyEmployee;public class Test_Show { public static void main(String[] args) { Employee boss = new Boss("虎哥", 10000, 50000); waiter waiter01 = new waiter("杀马特团长", 12000); Test1 test1 = new Test1(); // //实参是子类类型 System.out.println(boss.getName() + " 薪资 " + test1.ShowEmp_annual(boss)); // //实参是子类类型 System.out.println(waiter01.getName() + " 薪资 " + test1.ShowEmp_annual(waiter01)); test1.Test_work(waiter01);//实参是子类类型 }}package com.Deal.PloyEmployee;public class Test1 { public double ShowEmp_annual(Employee e){ //形参是父类类型的引用 运行类型是子类根据子类类型去调用getAnnual方法 return e.getAnnual(); } public void Test_work(Employee e){ if(e instanceof waiter){//判断e的运行类型是不是waiter ((waiter)e).work();//向下转型 //父类引用指向子类对象,向下转型之后才能调用work方法 } else if(e instanceof Boss){ ((Boss)e).manage();//和以上同理 } }}package com.Deal.PloyEmployee;public class waiter extends Employee { public waiter(String name, double salary) { super(name, salary); } @Override public double getAnnual() {//和父类构成重写 return super.getAnnual(); } public void work(){//特有方法 System.out.println("work方法被调用..."); }}package com.Deal.PloyEmployee;public class Boss extends Employee {private double bonus; public Boss(String name, double salary, double bonus) { super(name, salary); this.bonus = bonus; } @Override public double getAnnual() {//和父类构成重写 return super.getAnnual()+bonus; } public void manage(){//特有的方法 System.out.println("manage方法被调用!!!"); }}package com.Deal.PloyEmployee;public class Employee {//父类 private String name; private double salary; public Employee(String name, double salary) { this.name = name; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public double getAnnual(){ return salary*12; }}
==详解
两个引用之间 进行比较时,比较的是地址值跟编译类型没有关系,只要是两个引用同时都指向同一个对象就是true
JDK的源码—equals
package com.Deal.PloyEmployee;public class Test2 { public static void main(String[] args) { "helli".equals("world"); /* public boolean equals(Object anObject) { if (this == anObject) {//比较的是地址值,相等返回true return true;//this就是调用者的地址 } if (anObject instanceof String) {//判断anObj的运行类型是不是String String anotherString = (String)anObject;//向下转型强转为String int n = value.length; if (n == anotherString.value.length) {//判断两个串长度一样嘛 char v1[] = value;//把地址给了v1 char v2[] = anotherString.value;//把地址给了v2 int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false;//若出现不一样的元素放回false i++; }//while_end return true; }//内层if_end }//外层if_end return false;//若两者运行类型不一样返回false } */ //看看 Object 类的 equals 是/*//即 Object 的 equals 方法默认就是比较对象地址是否相同//也就是判断两个对象是不是同一个对象.public boolean equals(Object obj) {return (this == obj);}*///从源码可以看到 Integer 也重写了 Object 的 equals 方法,//变成了判断两个值是否相同//// public boolean equals (Object obj){// if (obj instanceof Integer) {// return value == ((Integer) obj).intValue();//// }// return false;// } Integer integer1 = new Integer(1000); Integer integer2 = new Integer(1000); System.out.println(integer1 == integer2); //比较的是地址值,两个不同的对象返回的地址肯定不同---false System.out.println(integer1.equals(integer2)); //判断的值,两个值都是一样的肯定没问题---true String str1 = new String("hello"); String str2 = new String("hello"); System.out.println(str1 == str2); //比较的地址---false System.out.println(str1.equals(str2)); //比较值---true }}
equals练习1
package com.Deal.PloyEmployee;public class Equals_Detail { public static void main(String[] args) { Person person1 = new Person("张三",10,'男'); Person person2 = new Person("张三",10,'男'); //System.out.println(person1.equals(person2));--false //Person类里面没有equals,因为任何类都是继承Object类,所以调用Object里面的 //equals方法返回false //自己重写的equals方法 System.out.println(person1.equals(person2));//--true }}class Person{ private String name; private int age; private char gender;//性别public boolean equals(Object obj){ //obj的运行类型是Person但是这里是Object来接受会发生向上转型,obj可以访问父类的 //所有方法属性(遵守访问权限); if(this==obj){ return true; } if(obj instanceof Person){ //向下转型 Person TT=(Person)obj; //TT可以访问子类的所有方法属性 return this.name.equals(TT.name)&&this.age==TT.age&&this.gender==TT.gender; } return false;} public Person(String name, int age, char gender) { this.name = name; this.age = age; this.gender = gender; } 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; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; }}
equals练习2
package com.Deal.PloyEmployee;public class Person_ { public static void main(String[] args) { Person2 p1 = new Person2(); p1.name = "hello"; Person2 p2 = new Person2(); p2.name = "hello"; System.out.println(p1 == p2); //False //==比较引用是判断值 System.out.println(p1.name.equals(p2.name)); //string是Object的子类重写了equals 返回--true比较字符串的内容 System.out.println(p1.equals(p2));//False //p1和p2是Person类型的引用没有重写equals 方法所以调用Object的equals方法 //--false String s1 = new String("asdf"); String s2 = new String("asdf"); System.out.println(s1.equals(s2));//比较字符串--true System.out.println(s1 == s2); // 比较的地址值--false }}class Person2 {//类 public String name;}
初识hashCode
1) 提高具有哈希结构的容器的效率!
2) 两个引用, 如果指向的是同一个对象, 则哈希值肯定是一样的!
3) 两个引用, 如果指向的是不同对象, 则哈希值是不一样的
4) 哈希值主要根据地址号来的! , 不能完全将哈希值等价于地址。
public class hashCode_ { public static void main(String[] args) { AA aa = new AA(); AA aa2 = new AA(); AA aa3 = aa; System.out.println("aa.hashCode()=" + aa.hashCode()); System.out.println("aa2.hashCode()=" + aa2.hashCode()); System.out.println("aa3.hashCode()=" + aa3.hashCode());//java虚拟机把地址转换为的hashCode值不是真正地址// aa.hashCode()=356573597 // aa2.hashCode()=1735600054// aa3.hashCode()=356573597 } } class AA {}
toString
1) 基本介绍
默认返回: 全类名+@+哈希值的十六进制, 【查看 Object 的 toString 方法】
子类往往重写 toString 方法, 用于返回对象的属性信息
2) 重写 toString 方法, 打印对象或拼接对象时, 都会自动调用该对象的 toString 形式.
3) 当直接输出一个对象时, toString 方法会被默认的调用, 比如 System.out.println(monster); 就会默认调用monster.toString()
package com.Deal.PloyEmployee;public class ToString { public static void main(String[] args) { monster monster1 = new monster("张三", 20, 1000); /* Object 的 toString() 源码 (1)getClass().getName() 类的全类名(包名+类名 ) (2)Integer.toHexString(hashCode()) 将对象的 hashCode 值转成 16 进制字符串 public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode());}*/ //System.out.println(monster1.toString()); //没重写tostring之前,调用Object类的toString是把该引用的hashCode值转换为16进制字符串// 重写之后看如何写的 System.out.println(monster1.toString()); System.out.println(monster1);//这个等价于上面 }}class monster { private String name; private int age; private double salary; @Override public String toString() {//重写后, 一般是把对象的属性值输出, 当然程序员也可以自己定制 return "monster{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } public monster(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; }}
finalize 方法
1) 当对象被回收时, 系统自动调用该对象的 finalize 方法。 子类可以重写该方法, 做一些释放资源的操作
2) 什么时候被回收: 当某个对象没有任何引用时, 则 jvm 就认为这个对象是一个垃圾对象, 就会使用垃圾回收机制来销毁该对象, 在销毁该对象前, 会先调用 finalize 方法。
3) 垃圾回收机制的调用, 是由系统来决定(即有自己的 GC 算法), 也可以通过 System.gc() 主动触发垃圾回收机制, 测试
package com.Deal.PloyEmployee;public class Finalize_ { public static void main(String[] args) { Car bmw = new Car("宝马");//这时 car 对象就是一个垃圾,垃圾回收器就会回收(销毁)对象, 在销毁对象前, 会调用该对象的 finalize 方法//,程序员就可以在 finalize 中, 写自己的业务逻辑代码(比如释放资源: 数据库连接,或者打开文件..)//,如果程序员不重写 finalize,那么就会调用 Object 类的 finalize, 即默认处理 //,如果程序员重写了 finalize, 就可以实现自己的逻辑 bmw = null; System.gc();//主动调用垃圾回收器 System.out.println("程序退出了...."); }}class Car { private String name; //属性, 资源。 。 public Car(String name) { this.name = name; } // //重写 finalize @Override protected void finalize() throws Throwable { System.out.println("我们销毁 汽车" + name); System.out.println("释放了某些资源..."); }}
Day15
断点调试
断点调试的快捷键
F7(跳入)
F8(跳过)
shift+F8(跳出)
F9(resume,执行到下一个断点)
F7: 跳入方法内
F8: 逐行执行代码.
shift+F8: 跳出方法
F8逐条向下执行
配置F7
ok了
这样就可以查看源码了
进入之后退出按 shift+f8
断点调试练习题
代码:
package com.Deal;public class Debug2 { public static void main(String[] args) { Person person = new Person("张三",18); System.out.println(person); }}class Person{ private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}
解读:
Day16
零钱通程序,面向过程版
package com.Deal.SmallChange;import java.sql.SQLOutput;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Scanner;public class SmallchangeSys { public static void main(String[] args) { // 1.完成显示菜单,以及选项,对应提示 //2.完成零钱通明细 利用字符串拼接 //3. 完成收益入账---设计两个变量 //4. 消费--创建变量商品名称 //5.退出 //6.确认是否退出y/n 必须输入y/n String details = "--------------零钱通明细-------------"; double money = 0; double total = 0; boolean loop = true; Scanner scanner = new Scanner(System.in); String key = ""; //把时间类型转换为中国样式 //引入java.util.Date当前日期 Date date = new Date(); SimpleDateFormat sdg = new SimpleDateFormat("yyyy-MM-dd HH:mm"); String note = "";//消费产品名称 //创建一个空字符串 输入判断是否真正退出!!! String choice = ""; do { System.out.println("\n--------------零钱通项目-------------"); System.out.println("\t\t\t1 零钱通明细"); System.out.println("\t\t\t2 收益入账"); System.out.println("\t\t\t3 消费"); System.out.println("\t\t\t4 退 出"); System.out.print("请输入选项(1-4): "); key = scanner.next(); //用switch进行分支判断 switch (key) { case "1": System.out.println(details); break; case "2": System.out.print("输入金额: "); money = scanner.nextDouble(); //校验入账金额合理嘛 //用找错误条件的方法退出,不要找正确的这样会麻烦 //如果不合理就break退出否者就顺序向下执行 if(money<=0){ System.out.println("入账金额需大于 0"); break; } total += money; //拼接收益入账信息 details += "\n收益入账\t+" + money + "\t" + sdg.format(date) + "\t" + total; //System.out.println("\t\t\t2 收益入账"); break; case "3": System.out.print("输入消费金额: "); money = scanner.nextDouble(); //校验消费金额合理嘛 if(money<0||money>total){ System.out.println("消费金额应该在:0-"+total); break; } total -= money; System.out.print("请输入消费的产品名称: "); note = scanner.next(); details += "\n" + note + "\t-" + money + "\t" + sdg.format(date) + "\t" + total; break; case "4": while (true) { System.out.println("请输入是否退出:y/n"); choice = scanner.next(); if ("y".equals(choice) || "n".equals(choice)) {break; } } //一个代码块,完成一个功能 if ("y".equals(choice)) { loop = false; break; } break; default: System.out.println("输入有误,请重写输入..."); } } while (loop); System.out.println("-------------退出零钱通-------------"); }}
零钱通OOP版
package com.Deal.SmallChange;public class SmallChangeOOPAPP { public static void main(String[] args) { //这样只能调用一次 new SmallChangeSysOOP().mainMenu(); }}package com.Deal.SmallChange;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Scanner;public class SmallChangeSysOOP { String details = "--------------零钱通明细-------------"; double money = 0; double total = 0; boolean loop = true; Scanner scanner = new Scanner(System.in); String key = ""; //把时间类型转换为中国样式 //引入java.util.Date当前日期 Date date = new Date(); SimpleDateFormat sdg = new SimpleDateFormat("yyyy-MM-dd HH:mm"); String note = "";//消费产品名称 //创建一个空字符串 输入判断是否真正退出!!! String choice = ""; public void mainMenu(){ do { System.out.println("\n--------------零钱通项目(OOP)-------------"); System.out.println("\t\t\t1 零钱通明细"); System.out.println("\t\t\t2 收益入账"); System.out.println("\t\t\t3 消费"); System.out.println("\t\t\t4 退 出"); System.out.print("请输入选项(1-4): "); key = scanner.next(); //用switch进行分支判断 switch (key) { case "1": this.Detail(); break; case "2": this.revenue(); break; case "3": this.consume(); break; case "4": this.exit(); break; default: System.out.println("输入有误,请重写输入..."); } } while (loop); } //显示收支情况 public void Detail(){ System.out.println(details); } //入账功能 public void revenue(){ System.out.print("输入金额: "); money = scanner.nextDouble(); //校验入账金额合理嘛 //用找错误条件的方法退出,不要找正确的这样会麻烦 //如果不合理就break退出否者就顺序向下执行 if(money<=0){ System.out.println("入账金额需大于 0"); return;//不符合条件程序返回 } total += money; //拼接收益入账信息 details += "\n收益入账\t+" + money + "\t" + sdg.format(date) + "\t" + total; //System.out.println("\t\t\t2 收益入账"); } public void consume(){ System.out.print("输入消费金额: "); money = scanner.nextDouble(); //校验消费金额合理嘛 if(money<0||money>total){ System.out.println("消费金额应该在:0-"+total); return;//条件不合适返回 } total -= money; System.out.print("请输入消费的产品名称: "); note = scanner.next(); details += "\n" + note + "\t-" + money + "\t" + sdg.format(date) + "\t" + total; } public void exit(){ while (true) { System.out.println("请输入是否退出:y/n"); choice = scanner.next(); if ("y".equals(choice) || "n".equals(choice)) { break; } } //一个代码块,完成一个功能 if ("y".equals(choice)) { loop = false; return; } }}
练习题1
package com.Deal.Practice;import java.util.Scanner;public class Parctice01 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Person [] persons=new Person[3];//创建一个数组有三个Person类型的元素// 每个元素 persons=null 调用不了方法 for (int i = 0; i < persons.length; i++) { System.out.println("请输入第"+(i+1)+"人的:名字 年龄 工作"); Person person = new Person("lis",12,"13");// 借助一个临时变量来把输入的之赋值给数组元素 person.setName(scanner.next());//输入名字 person.setAge((scanner.nextInt()));//输入年龄 person.setJob(scanner.next());//输入job //赋值功能 persons[i]=person; } //冒泡排序 for (int i = 0; i < persons.length-1; i++) { for (int j = 0; j < persons.length-1-i; j++) { if(persons[j].getAge()<persons[j+1].getAge()){ Person tmp = null; tmp=persons[j]; persons[j]=persons[j+1]; persons[j+1]=tmp; } } } //打印 for (int i = 0; i < persons.length; i++) { System.out.println(persons[i]); //persons[i] ~persons[i].toString 重写了 } }}public class Person {private String name; private int age; private String job; public Person(String name, int age, String job) { this.name = name; this.age = age; this.job = job; } 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; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", job='" + job + '\'' + '}'; }}
练习题2
package com.Deal.Practice;public class Porfessor_Test { public static void main(String[] args) { Porfessor porfessor = new Porfessor("张三", 38, "好果汁大学教授", 20000,1.3); System.out.println(porfessor.introduce()); }}package com.Deal.Practice;public class Porfessor extends Teacher {//子类 public Porfessor(String name, int age, String post, double salary,double grade) { super(name, age, post, salary,grade); } public String introduce(){//和父类重写 return super.introduce(); }}package com.Deal.Practice;public class Teacher {//父类 private String name; private int age; private String post; private double salary; private double grade; public Teacher(String name, int age, String post, double salary,double grade) { this.name = name; this.age = age; this.post = post; this.salary = salary; this.grade=grade; } 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; } public String getPost() { return post; } public void setPost(String post) { this.post = post; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public String introduce(){//重写 return "name:"+name+"\tage:"+age+"\tpost:"+post+"\tsalary:"+salary+"\tgrade:"+grade; }}
练习题3
package com.Deal.Practice;public class Employee {//父类 private String name; private double money; private double days; private double grade; public Employee(String name, double money, double days,double grade) { this.name = name; this.money = money; this.days = days; this.grade=grade; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; } public double getDays() { return days; } public void setDays(double days) { this.days = days; } public double getGrade() { return grade; } public void setGrade(double grade) { this.grade = grade; } public void GetSalary(){//和子类方法重写 System.out.println(name+"\t"+"工资:"+getDays()*getMoney()*getGrade()); }}package com.Deal.Practice;public class Worker extends Employee { public Worker(String name, double money, double days,double grade) { super(name, money, days, grade); } @Override public void GetSalary() { System.out.print("员工:"); super.GetSalary();//没有特定的属性直接调用 }}package com.Deal.Practice;public class Manager extends Employee { private double prize;//子类特有 public Manager(String name, double money, double days,double grade) { super(name, money, days,grade); } @Override public void GetSalary() { //综合工资 System.out.println("经理:"+getName()+"\t"+"工资:"+"\t"+(prize+ getMoney()*getDays()*getGrade())); }}package com.Deal.Practice;public class Homework03 { public static void main(String[] args) { Manager tom = new Manager("张三", 200, 60,1.2); Worker mary = new Worker("李四", 180, 30,1.0); tom.GetSalary(); mary.GetSalary(); }}
练习题4
package com.Deal.Practice;public class Homework05 { public static void main(String[] args) { waiter tom = new waiter("tom", 3000, 12); teachers mary = new teachers("mary", 3000, 12, 80, 80); mary.setClassDay(300); mary.setClassSal(180); Scientist her = new Scientist("her", 9000, 12); her.setBonus(300000); tom.Print(); mary.Print(); her.Print(); }}package com.Deal.Practice;public class waiter extends Emoploy { public waiter(String name, double sal, int month) { super(name, sal, month); } @Override public void Print() {//服务类没有额外的东西 System.out.print("服务员: "); super.Print(); }}package com.Deal.Practice;public class teachers extends Emoploy { private int classDay; private double classSal; public teachers(String name, double sal, int month, int classDay, double classSal) { super(name, sal, month); this.classDay = classDay; this.classSal = classSal; } @Override public void Print() { // 基础工资+课时费 System.out.println("老师: "+getName()+"\t"+"薪资:"+(getMonth()*getSal()+classDay*classSal)); } public int getClassDay() { return classDay; } public void setClassDay(int classDay) { this.classDay = classDay; } public double getClassSal() { return classSal; } public void setClassSal(double classSal) { this.classSal = classSal; }}package com.Deal.Practice;public class Scientist extends Emoploy { private double bonus; @Override public void Print() { // 工资+年终奖 System.out.println("科学家: "+getName()+"\t"+"薪资:"+(getMonth()*getSal()+bonus)); } public Scientist(String name, double sal, int month) { super(name, sal, month); } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; }}package com.Deal.Practice;public class Emoploy {//父类 private String name; private double sal; //重写打印方法 private int month; public void Print(){ System.out.println(name+"\t"+"薪资:"+(sal*month)); } public Emoploy(String name, double sal,int month) { this.name = name; this.sal = sal; this.month=month; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSal() { return sal; } public void setSal(double sal) { this.sal = sal; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; }}
练习题5
练习题7
练习题8
package com.Deal.Practice;public class Homework08 { public static void main(String[] args) { CheckingAccount checkingAccount = new CheckingAccount(1000); checkingAccount.deposit(100); System.out.println(checkingAccount.getBalance());//1099 earnMonthlyinterest earnMonthlyinterest = new earnMonthlyinterest(1000); earnMonthlyinterest.deposit(100); earnMonthlyinterest.deposit(100); earnMonthlyinterest.deposit(100); System.out.println(earnMonthlyinterest.getBalance()); earnMonthlyinterest.deposit(100); System.out.println(earnMonthlyinterest.getBalance()); earnMonthlyinterest.earninterest();//1399*0.01=13.99利息 System.out.println(earnMonthlyinterest.getBalance()); }}package com.Deal.Practice;public class BankAccount { private double balance; //存款方法 public void deposit(double amount ){ this.balance+=amount; } //取款方法 public void withdraw(double amount){ this.balance-=amount; } public BankAccount(double balance) { this.balance = balance; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; }}package com.Deal.Practice;public class earnMonthlyinterest extends BankAccount { private int count =3;//免费存取三次 private double rate=0.01;//利率 public earnMonthlyinterest(double balance) { super(balance); } public void earninterest(){ count=3; super.deposit(rate*getBalance()); //把利息存上去 } @Override public void deposit(double amount) { if(count>0) { super.deposit(amount); } else { super.deposit(amount-1);//三次以上收取手续费 } count--; } @Override public void withdraw(double amount) { if(count>0) { super.withdraw(amount); } else { super.withdraw(amount+1);//三次以上收取手续费 } count--; }}package com.Deal.Practice;public class CheckingAccount extends BankAccount { //没有特有的属性 public CheckingAccount(double balance) { super(balance); } //每存一次手续费1美元 @Override public void deposit(double amount) { //重写的好处就是存或取的逻辑不变,我们只完成收取手续费的逻辑 super.deposit(amount-1);//减去的1元当手续费 } @Override public void withdraw(double amount) { super.withdraw(amount+1);//多加1美元当取出的手续费 }}
练习题9
package com.Deal.Practice;public class Homework10 { public static void main(String[] args) { Doctor doctor = new Doctor("张三", 29, "妇科", '女', 10000); Doctor doctor01 = new Doctor("lisi", 29, "妇科", '女', 10000); if(doctor.equals(doctor01)){ System.out.println("相等"); } else { System.out.println("不相等"); } }}package com.Deal.Practice;import java.util.Objects;public class Doctor { private String name; private int age; private String job; private char gender; private double sal; @Override public boolean equals(Object o) { if (this == o) { return true;//如果引用值一样,返回true } //过关斩将 //先判断o是不是Doctor的运行类型或者其子类型 if (!(o instanceof Doctor)) { return false; } Doctor doctor = (Doctor) o;//向下转型 转为Doctor才能访问其成员 //否则O的只能其父类的成员 return this.name.equals(((Doctor) doctor).name) && this.age == doctor.age && this.gender == doctor.gender && this.job.equals(doctor.job) && this.sal == doctor.sal; } public Doctor(String name, int age, String job, char gender, double sal) { this.name = name; this.age = age; this.job = job; this.gender = gender; this.sal = sal; }}
练习题10*
练习题11 ==和equals的区别
练习题12*
对排序的理解
package com.Deal.Practice;import com.test.Student;public class Homework13 { public static void main(String[] args) { student1 stu1 = new student1("张三", '男', 19, "打火机", 1); student1 stu2 = new student1("李四", '男', 22, "窜雪地", 2); teacher1 tea1 = new teacher1("李明", '男', 28, "大砍刀", 3); teacher1 tea2 = new teacher1("王小花", '女', 28, "松果谈吐闪电鞭", 1);// stu1.printInfo();// stu2.printInfo();// tea1.printInfo();// tea2.printInfo();创建多态数组 Person1[] person1s = new Person1[4]; //类型名 数组名 创建有四个Person1类型的数组 person1s[0] = new student1("虎哥", '男', 98, "玫瑰花树", 12); person1s[1] = new student1("刀哥", '男', 100, "油桶子", 13); person1s[2] = new teacher1("杀马特团长", '女', 120, "头套", 2); person1s[3] = new teacher1("小亮", '男', 99, "爬犁", 34); //((student1) person1s[0]).printInfo(); Homework13 homework13 = new Homework13(); homework13.Sort(person1s); } public void Sort(Person1[] p) { Person1 tmp = null; for (int i = 0; i < p.length - 1; i++) { for (int j = 0; j < p.length - 1 - i; j++) { //父类引用指向子类对象所以引用,子类对象的地址放到数组元素的那个元素里面都没事呀 //因为student1和teacher1的编译类型的都是一样的,排序只是把地址排序了 if (p[j].getAge() < p[j + 1].getAge()) { tmp = p[j]; p[j] = p[j + 1]; p[j + 1] = tmp; } } } //打印排序后的数组, for (int i = 0; i < p.length; i++) { if (p[i] instanceof student1) { ((student1) p[i]).printInfo(); } else if (p[i] instanceof teacher1) { ((teacher1) p[i]).printInfo(); } } }}package com.Deal.Practice;public class student1 extends Person1{ private int stu_id; public student1(String name, char sex, int age, String tool, int stu_id) { super(name, sex, age, tool); this.stu_id = stu_id; } @Override public void play() {//和父类重写 System.out.print("老师:"); super.play(); } public String study(){//特有方法 return "我是学生,我承诺,认真学习..."; } public void printInfo(){ //打印方法 System.out.println("学生信息:\n"+super.Baseprint()+"\n学号:"+this.stu_id+"\n"+ study()); super.play(); System.out.println("====================================================="); }}package com.Deal.Practice;public class teacher1 extends Person1 { private int work_age; public teacher1(String name, char sex, int age, String tool, int work_age) { super(name, sex, age,tool); this.work_age = work_age; } @Override public void play() {//和父类重写 System.out.print("老师:"); super.play(); } public String teach(){//特有方法 return "我是老师,我承诺,认真教书..."; } public void printInfo(){ //打印方法 System.out.println("老师信息:\n"+super.Baseprint()+"\n工龄:"+this.work_age+"\n"+ teach()); super.play(); System.out.println("====================================================="); }}package com.Deal.Practice;public class Person1 { private String name; private char sex; private int age; private String tool; public void play() { System.out.println(name+"爱玩"+tool); } public Person1(String name, char sex, int age,String tool) { this.name = name; this.sex = sex; this.age = age; this.tool=tool; } public String Baseprint(){ return "姓名: "+name+"\n年龄: "+age+"\n性别: "+sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
练习题13
Day17
房屋出租系统
代码实现
package com.Deal.HouseProject;import com.Deal.HouseProject.View.HouseView;public class HouseRentApp { public static void main(String[] args) { new HouseView().mainMenu(); System.out.println("===退出房屋出租系统==="); }}package com.Deal.HouseProject.View;import com.Deal.HouseProject.Domain.Home;import com.Deal.HouseProject.Service.HouseService;import com.Deal.HouseProject.utils.Utility;public class HouseView { private boolean loop = true; private char key = ' '; private HouseService houseService = new HouseService(2);//用有参构造器来指定数组大小 ///2 查 找 房 源 public void FindHouse() { System.out.println("\n===========查 找 房 源 页 面============"); System.out.println("======按编号查(1) 按地址查(2)===="); int flag = Utility.readInt(); if (flag == 2) { //按name查找 System.out.print("请输入查找的(Address):"); String Address = Utility.readString(12); Home[] tempHomes = houseService.FindByAddress(Address); if (tempHomes != null) { for (int i = 0; i < tempHomes.length; i++) { if (tempHomes[i] != null) {//打印ByAddress找的房源 System.out.println(tempHomes[i]); } } } else { System.out.println("没有找到该地址的房源..."); } } else if (flag == 1) { //按id查找 id是唯一的 System.out.print("请输入查找的(id):"); int id = Utility.readInt(); Home tempHome = houseService.FindById(id); if(tempHome!=null){ System.out.println(tempHome); } else { System.out.println("by address no find..."); } } else { System.out.println("选择有误..."); return; } } //修 改 房 源 信 息 public void modifyHouse() { System.out.println("\n===========修 改 房 源 页 面============"); System.out.print("请输入修改房屋的编号退出输入(-1):"); int id = Utility.readInt(); if (id == -1) { System.out.println("----------放 弃 删 除 房 源-----------"); return; } if (houseService.modify(id)) { System.out.println("-----修改成功-----"); } else { System.out.println("---未找到id,修改失败---"); } } //6 退出 public void exitHouse() { System.out.println("确认退出输入Y,否N:"); char choice = Utility.readConfirmSelection(); if (choice == 'Y') { loop = false; } } //2 删 除 房 源 public void delHouse() { System.out.println("\n===========删 除 房 源 页 面============"); System.out.print("请选出删除房源的编号(-1)退出:"); int id = Utility.readInt(); if (id == -1) { System.out.println("----------放 弃 删 除 房 源-----------"); return; } System.out.print("请小心删除!确认是否删除:(Y/N):"); char c = Utility.readConfirmSelection();//该方法必须输入Y/N才行 if (c == 'N') { System.out.println("放弃删除房源信息..."); } else { if (houseService.del(id)) { System.out.println("删除成功"); } else { System.out.println("-----id 不 存 在 删 除 失 败-----"); } } } //1 新 增 房 源 public void addHouse() { System.out.println("\n===========添 加 房 源============"); System.out.print("姓名:"); String name = Utility.readString(6, "傻逼 "); System.out.print("电话:"); String phone = Utility.readString(12, "000000"); System.out.print("地址: "); String address = Utility.readString(16, "沈阳大街"); System.out.print("月租: "); int rent = Utility.readInt(); System.out.print("状态(已出租/未出租): "); String state = Utility.readString(12, "未出租"); Home newHouse = new Home(0, name, phone, address, rent, state); //调用add方法 if (houseService.add(newHouse)) { System.out.println("===========添 加 房 源 完 成============"); } else { System.out.println("===========添 加 房 源 失 败============"); } } // 展示房源列表 public void HouseList() { System.out.println("\n============房 源 列 表============"); System.out.println("编号\t房主\t\t电话\t\t\t地址\t\t月租\t\t状态"); Home[] houses = houseService.list();//调用list方法返回一个数组名 (返回了所有房源信息) for (int i = 0; i < houses.length; i++) { if (houses[i] == null) { break; } System.out.println(houses[i].toString()); //houses[i]是一个对象类型是Home Home里面重写了toString } System.out.println("==========房 源 列 表 完 成=========="); } public void mainMenu() { do { System.out.println("\n==========房屋出租系统菜单=========="); System.out.println("\t\t\t1 新 增 房 源"); System.out.println("\t\t\t2 查 找 房 源"); System.out.println("\t\t\t3 删 除 房 源"); System.out.println("\t\t\t4 修 改 房 源 信 息"); System.out.println("\t\t\t5 房 源 列 表"); System.out.println("\t\t\t6 退 出"); System.out.print("请输入选项(1-6): "); key = Utility.readChar(); switch (key) { case '1': addHouse(); break; case '2': FindHouse(); break; case '3': delHouse(); break; case '4': modifyHouse(); break; case '5': HouseList(); break; case '6': exitHouse(); break; } } while (loop); }}package com.Deal.HouseProject.Service;import com.Deal.HouseProject.Domain.Home;import com.Deal.HouseProject.utils.Utility;/ * 创建homes [] 数组存放Home成员,利用构造器来指定数组大小 * list返回数组名 */public class HouseService { private Home[] homes;//声明 homes=null private int homesNum = 1;//数组下标,当前数组存放一个成员 private int idCount = 1;//因为数组里面有一个元素了 //构造器有参的 让调用者指定大小 public HouseService(int size) { homes = new Home[size];//创建size大小的数组 homes[0] = new Home(1, "虎哥", "138143819438", "沈阳大街", 3000, "未出租"); } //返回数组名 public Home[] list() { return homes; } //返回boolean 来判断添加是否成功 public boolean add(Home newHouse) {//形参是Home类型 //计数下标>=数组长度退出 if (homesNum >= homes.length) {//--添加数组增容功能 char ch; do { System.out.print("您数组已满!!!,增容(Y),否(N):"); ch = Utility.readChar(); if (ch == 'N') { System.out.println("数组已满,添加失败!!!"); return false; } if (ch == 'Y') { System.out.println("您选择了增容功能..."); Home homeTemp[] = new Home[homes.length + 1];//创造一个比之前大1个的大数组 for (int i = 0; i < homes.length; i++) { homeTemp[i] = homes[i];//把之前的数据拷贝进去 } homes = homeTemp;//homes存放当前homeTemp这个数组的地址,换句话就是指向这个扩容的数组 //之前的homes数组就被垃圾回收系统回收了 System.out.println("增容成功..."); break;//添加完之后break退出继续执行 } else { System.out.println("输入错误,请重新输入:Y/N..."); } } while (true); //return false; } homes[homesNum++] = newHouse;//添加的对象放到数组(即把地址放到指针变量) //设计一个id的自增长模式 设计newHouse里面id自增长 newHouse.setId(++idCount);//调用set函数 return true; } //删除方法 public boolean del(int delId) { int index = -1; for (int i = 0; i < homesNum; i++) {//要在数组元素个数里面对比 if (delId == homes[i].getId()) { index = i;//不能直接delId-1 因为要是多次删除id的数组下标没有相对循序 } } if (index == -1) { System.out.println("没有找的该Id...."); return false; } //完成删除功能 for (int i = index; i < homesNum - 1; i++) { homes[i] = homes[i + 1];//index 下标的数依次向前挪 } homes[--homesNum] = null;//最后一个置为空因为打印逻辑是null不打印且homesNum数组下标-1 return true; } //完成修改功能 public boolean modify(int modify_id) { int index = -1; for (int i = 0; i < homesNum; i++) { if (homes[i].getId() == modify_id) { index = i;//找到了id所在的元素下标 } } if (index == -1) { return false;//没找到id } //完成修改功能 System.out.print("姓名" + "(" + homes[index].getName() + "):"); homes[index].setName(Utility.readString(12));//输入名字 System.out.print("电话" + "(" + homes[index].getPhone() + "):"); homes[index].setPhone(Utility.readString(12)); System.out.print("地址" + "(" + homes[index].getAddress() + "):"); homes[index].setAddress(Utility.readString(12)); System.out.print("租金" + "(" + homes[index].getRent() + "):"); homes[index].setRent(Utility.readInt()); System.out.print("状态" + "(" + homes[index].getState() + "):"); homes[index].setState(Utility.readString(12)); return true; } //完成查找功能 public Home FindById(int findId) { for (int i = 0; i < homesNum; i++) {//在已有的房源里面查找 if (homes[i].getId() == findId) { return homes[i]; } } return null; } //按地址查找 地址可能不止一个 public Home[] FindByAddress(String findAddress) { Home[] tempHomes = new Home[homesNum];//声明一个当前数组大小的数组用来存放找到的数组 int index = 0; for (int i = 0; i < homesNum; i++) {//在已有的房源里面查找 if (homes[i].getAddress().equals(findAddress)) { tempHomes[index++] = homes[i];//找到了把该元素地址放到temp数组 } } if(index==0) { return null; } else return tempHomes; }}package com.Deal.HouseProject.Domain;public class Home { private int id; private String name; private String phone; private String address; private int rent; private String state; public Home(int id, String name, String phone, String address, int rent, String state) { this.id = id; this.name = name; this.phone = phone; this.address = address; this.rent = rent; this.state = state; } 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 String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getRent() { return rent; } public void setRent(int rent) { this.rent = rent; } public String getState() { return state; } public void setState(String state) { this.state = state; } @Override public String toString() { return id+"\t"+name+"\t"+phone+"\t"+address+"\t"+rent+"\t"+state; }}
Day18面向对象高级部分
静态变量的内存布局
结论:
类变量的定义与使用
没有创建对象就可以用类名调用静态变量,说明随着类加载静态变量就生成了
可以用对象名调用静态变量
类变量细节
静态方法 模拟学生缴费
package com.Chapter.Static_;import java.util.Scanner;public class staticMethod { public static void main(String[] args) { Stu tom = new Stu("tom"); Stu.AddFee(100);//类名直接调用静态方法 Stu mary = new Stu("mary"); tom.AddFee(200);// tom.ShowFee(); }}class Stu{ private String name; //static变量同类所用对象共享 public static double static_Fee=0; public Stu(String name) { this.name = name; } public static void AddFee(double fee){ static_Fee+=fee; } public static void ShowFee(){ System.out.println(static_Fee); }}
静态方法的实例
static方法用途是,制造工具类,不用创建对象,方便调用
静态方法的细节
// 不能在静态方法里面调用非静态方法或属性,因为非静态方法要创建了对象之后才能调用
//静态的在类加载时候,就随之加载出来了,所以不能在静态方法里面调用非静态的
public class staticMethod { public static void main(String[] args) { Stu.test(); }}class Stu { private String name; //static变量同类所用对象共享 private static int n1 = 0; public void see() { System.out.println("this is no static method"); } public static void show() { System.out.println("this is static method"); } public static void test() { //System.out.println(this.name); //不能在静态方法里面使用this super和对象有管的关键字 //System.out.println(name);// 不能在静态方法里面调用非静态方法或属性,因为非静态方法要创建了对象之后才能调用 //静态的在类加载时候,就随之加载出来了,所以不能在静态方法里面调用非静态的//在静态方法里面调用静态的没问题 System.out.println(n1); show(); } public void test1() { System.out.println(this.name); show();//调用静态的也没问题 }}
理解main方法语法
1)在 main()方法中, 我们可以直接调用 main 方法所在类的静态方法或静态属性。
2) 但是, 不能直接访问该类中的非静态成员, 必须创建该类的一个实例对象后, 才能通过这个对象去访问类中的非静态成员.
package com.Chapter.Static_;public class static_main { public int n1=0; public int n2=1; public void see(){ System.out.println("you can see me"); } public static void main(String[] args) { //在main中也和普通的方法一样,能调用静态的,不能调用非静态的 //如何调用非静态的呢,创建一个对象 static_main static_main1 = new static_main(); static_main1.see();//这样就可以调用了哦 }}
main的动态传参
package com.Chapter.Static_;public class main1 { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("args["+(i+1)+"]= "+args[i]); } } }
Day19
代码块入门
class TestBlock{ public static void main(String[] args) { //代码块在构造器器调用之前调用 codeBlock codeBlock = new codeBlock(); codeBlock tom = new codeBlock("李焕英"); }}public class codeBlock { private String name; { System.out.println("you can see me"); } public codeBlock() { System.out.println("codeBlock():"); } public codeBlock(String name) { this.name = name; System.out.println("codeBlock(String name)"); }}
代码块细节1
package com.Chapter.Block;public class test01 { public static void main(String[] args) { //类加载的三种情况 //1.创建实例是会被加载(new)// AA aa = new AA(); //2.创建子类对象时父类也会被加载 //BB bb = new BB();//BB类继承AA类 //3.使用类的静态成员时会被加载//静态的只会加载一次// System.out.println(AA.n1);// System.out.println(AA.n1); System.out.println(BB.see); //你不创建对象,在调用子类静态成员时父类也会被加载 }}class AA{ public static int n1=9999; static { System.out.println("我是AA的静态代码块"); } public AA() { System.out.println("AA类被加载..."); }}class BB extends AA{ public static String see="我是BB类的静态变量"; static { System.out.println("我是BB的静态代码块"); } public BB() { System.out.println("BB类被加载..."); }}
代码块细节2
public class test02 { public static void main(String[] args) { //System.out.println(A.n1); A a = new A(); //静态的是随着类加载被加载的,首先被调用,其次就是普通属性初始化和普通代码块(为啥比构造器快,要先完成显示初始化 // 再完成构造器初始化,否则先构造器初始化完之后,在显示初始化,你自定义的构造器初始化就会被显示初始化覆盖了) }}class A{ //构造器--最后被调用 public A() { System.out.println("我是无参构造器"); } //非静态方面--其次被调用 public int n2=getN2(); { System.out.println("我是普通代码块"); } public int getN2(){ System.out.println("普通getN2()方法被调用"); return 20; } //静态方面--首先被调用 public static int n1=getN1(); static { System.out.println("我是静态代码块"); } public static int getN1(){ System.out.println("静态getN1()方法被调用"); return 10; }}
代码块细节3
总之记住优先级:静态属性初始化和静态代码块>普通属性初始化和普通代码块>构造器
public class test03 { public static void main(String[] args) { //总之记住优先级:静态属性初始化和静态代码块>普通属性初始化和普通代码块>构造器 new BBB(); }}class AAA { { System.out.println("AAA()的普通代码块"); } public AAA() { //隐含super //隐含调用普通代码块的语句 System.out.println("AAA()构造器被调用!!!"); }}class BBB extends AAA { { System.out.println("BBB 的普通代码块"); } public BBB() { //隐含super //隐含调用普通代码块的语句 System.out.println("BBB()构造器被调用!!!"); }}
代码块细节4(面试题)
package com.Chapter.Block;public class test03 { public static void main(String[] args) { //总之记住优先级:静态属性初始化和静态代码块>普通属性初始化和普通代码块>构造器 new BBB(); }}class AAA { //静态方面 public static int n3=getN3(); public static int getN3(){ System.out.println("AAA 的静态赋值方法被调用");//(1) return 20; } static { System.out.println("我是AAA的静态代码块");//(2) } //普通方面 public int n4=getN4(); public int getN4(){ System.out.println("AAA 的普通赋值方法被调用");//(5) return 10; } { System.out.println("AAA()的普通代码块");(6) } //构造器方面 public AAA() { //隐含super //隐含调用普通代码块和普通属性初始化 System.out.println("AAA()构造器被调用!!!");//(7) }}class BBB extends AAA { //静态方面 public static int n2=getN2(); public static int getN2(){ System.out.println("BBB 的静态赋值方法被调用");//(3) return 20; } static { System.out.println("我是BBB的静态代码块");//(4) } //普通方面 public int n1=getN1(); public int getN1(){ System.out.println("BBB 的普通赋值方法被调用");//(8) return 10; } { System.out.println("我是BBB 的普通代码块");//(9) } //构造器方面 public BBB() { //隐含super //隐含调用普通代码块和普通属性初始化 System.out.println("BBB()构造器被调用!!!");//(10) }}
代码块练习
答案:
Day20
单例模式饿汉式
package com.Chapter.Single;public class single_hungry { public static void main(String[] args) {//1.构造器私有化防止直接new //2.在该类中创建对象,私有的static的 //3.再来一个返回对象的公共方法 System.out.println(Girl_friend.GetInstance()); }}class Girl_friend{ private String name; //私有的再另一个类不能调用 static的类加载只加载1次,故只创建1次 private static Girl_friend gf =new Girl_friend("张三"); private Girl_friend(String name) { this.name = name; } //必须是static的否则还有创建对象 public static Girl_friend GetInstance(){ return gf; } @Override public String toString() { return "Girl_friend{" + "name='" + name + '\'' + '}'; }}
懒汉式
package com.Chapter.Single;/ * 懒汉模式 */public class SingleLazy { public static void main(String[] args) { //1.构造器私有化 // 2.定义一个static的属性 //3.定义一个静态的公共的返回对象的方法 System.out.println(Cat.n1); }}class Cat { public static int n1=100; private String name; private static Cat cat;//声明对象不是创建懒汉式是直接创建 private Cat(String name) { this.name = name; } public static Cat GatInstance() { System.out.println("构造器被调用..."); if (cat == null) { cat = new Cat("小花"); } return cat; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + '}'; }}
final关键字
对于普通的成员赋值情况:
package com.Chapter.Final;public class finalDetail { public static void main(String[] args) { }}class A{ public final int n1=10;//定义时直接赋值 public final int n2; public final int n3; public A() {//再构造器中 n2 = 90; } //new一个对象的时候就会被赋值,赋值1次不能被修改 {//再代码块中 n3=10; } }
对于静态的成员赋值情况:
class B { public static final int N1; //不能再构造器里面 static {//可以在静态代码块中赋值 N1 = 10; } //不可以再普通代码块中赋值静态的final的属性,静态的只会被加载1次, //这样new一个对象static的N1就会被赋值,N1要是变换了,你在new赋新值何来静态之说// {// N1=2;// }}
final细节2
抽象类
public class Abstract01 { public static void main(String[] args) { //new AA()//抽象类不能初始化 }}abstract class AA { public abstract void see();//不能有主体 //private final void see1();不能出现final final一出必不能重写 //static 方法不能重写 }
模板设计模式
package com.Chapter.Abstract;public class AbstractExercise { public static void main(String[] args) { Test1 test1 = new Test1(); test1.calculate();//调用父类方法 test2 test2 = new test2(); test2.calculate();//调用父类方法 }}package com.Chapter.Abstract;abstract public class Test {//父类 public abstract void job();//abstract方法 public void calculate() { //公平的实现模块,这样设计代码复用性很高 //获得当前时间 long start = System.currentTimeMillis(); job(); long end = System.currentTimeMillis(); System.out.println("任务执行时间:" + (end - start)); }}package com.Chapter.Abstract;public class test2 extends Test { public void job(){ //独有实现方法 int num=0; for (int i = 0; i < 300000; i++) { num*=i; } }}package com.Chapter.Abstract;public class Test1 extends Test { public void job(){//独有的实现方法 int num=0; for (int i = 0; i < 800000; i++) { num+=i; } }}
执行路径:
Day21
接口入门
package com.Chapter.Interface;public class Interface01 { public static void main(String[] args) { camera camera1 = new camera(); phone phone1 = new phone(); computer computer1 = new computer(); computer1.work(camera1); System.out.println("========================="); computer1.work(phone1); }}package com.Chapter.Interface;public interface UsbInterface { public void start();//相当于里的协议 public void stop();}package com.Chapter.Interface;public class camera implements UsbInterface { //相机 实现接口里面的方法 @Override public void start() { System.out.println("相机开始工作..."); } @Override public void stop() { System.out.println("相机结束工作..."); }}package com.Chapter.Interface;public class computer { //计算机通过接口调用外设工作 public void work(UsbInterface usbInterface){ usbInterface.start(); usbInterface.stop(); }}package com.Chapter.Interface;public class phone implements UsbInterface{ //手机 实现接口里面的方法 @Override public void start() { System.out.println("手机开始工作..."); } @Override public void stop() { System.out.println("手机结束工作..."); }}
package com.Chapter.Interface;public interface AInterface { public int n=0;//可以又自己的属性 public void see();//再接口里面抽象方法可以不加abstract //JDK8 之后可以在里面实现方法 default public void see1(){ System.out.println("要加default"); } public static void see2(){ System.out.println("可以又静态方法"); }}
接口的具体应用场景
具体实现:
package com.Chapter.Interface;public class Interface02 { public static void main(String[] args) { Mysql mysql = new Mysql(); work(mysql); System.out.println("================="); Oracle oracle = new Oracle(); work(oracle); } public static void work(BInterface bInterface){ bInterface.connect(); bInterface.close(); }}package com.Chapter.Interface;public class Oracle implements BInterface { @Override public void connect() { System.out.println("连接Oracle"); } @Override public void close() { System.out.println("关闭Oracle"); }}package com.Chapter.Interface;public class Mysql implements BInterface { @Override public void connect() { System.out.println("连接Mysql"); } @Override public void close() { System.out.println("关闭Mysql"); }}public interface BInterface {//项目经理创建的 public void connect(); public void close();}
接口的细节
package com.Chapter.Interface;public class InterfaceDetail { public static void main(String[] args) { System.out.println(IA.n);//这就证明了是static的 }}interface IB{//接口只能是public和默认的修饰}interface IA{ int n=100;//等价与public static final int n=10 必须初始化 public void see();}//一个接口可以继承多个接口interface IN extends IA,IB{}//一个类可以实现多个接口class cat implements IA,IN{ @Override public void see() { }}
接口VS继承
小结: 当子类继承了父类, 就自动的拥有父类的功能
如果子类需要扩展功能, 可以通过实现接口的方式扩展.
可以理解 实现接口 是 对 java 单继承机制的一种补充
package com.Chapter.Interface;public class Test01 { public static void main(String[] args) { LittleMonkey wuKong = new LittleMonkey("悟空"); wuKong.climb(); wuKong.swimming(); }}class Monkey { private String name; public Monkey(String name) { this.name = name; } public void climb() { System.out.println(name + "会爬树..."); } public String getName() { return name; } public void setName(String name) { this.name = name; }}interface fish{ public void swimming();//默认是abstract}//小结: 当子类继承了父类, 就自动的拥有父类的功能// 如果子类需要扩展功能, 可以通过实现接口的方式扩展.// 可以理解 实现接口 是 对 java 单继承机制的一种补充class LittleMonkey extends Monkey implements fish{ public LittleMonkey(String name) { super(name); } @Override public void swimming() { System.out.println(getName()+"通过接口学会游泳了"); }}
接口的多态
package com.Chapter.Interface;public class InterfacePloy { public static void main(String[] args) { //接口的多态 IO temp = new AA(); //AA实现了IO接口 这样IO类型的引用指向AA对象 //对象的多态 Animal dog1=new dog(); //dog继承了Animal 父类引用指向了实现IO接口的对象 }}interface IO{ }class AA implements IO{};class BB implements IO{};class Animal{ }class dog extends Animal{}
参数的多态
接口数组
package com.Chapter.Interface;public class InterfacePloy { public static void main(String[] args) { Usb[] usbs = new Usb[2]; usbs[0]=new phone_(); usbs[1]=new camera_(); for (int i = 0; i < usbs.length; i++) { usbs[i].work(); if(usbs[i] instanceof phone_){ ((phone_) usbs[i]).Call();//向下转型 //父类的引用只能调用子类公共的不能调用特有的 } } }}interface Usb { void work();}class phone_ implements Usb { @Override public void work() { System.out.println("手机正在工作..."); } public void Call() {//独有的方法 System.out.println("手机可以打电话..."); }}class camera_ implements Usb { @Override public void work() { System.out.println("相机正在工作..."); }}
接口的多态传递
package com.Chapter.Interface;public class InterfacePloy { public static void main(String[] args) { //接口引用指向,实现了该接口的类的对象实例 IG ig=new TT(); IH ih=new TT();//IG继承了IH //所以IH类型的引用也可以指向TT类的对象实例 } }interface IH{}interface IG extends IH{}class TT implements IG{ }
public class InterfaceExercise02 {public static void main(String[] args) {}} interface A { // 1min 看看int x = 0;} //想到 等价 public static final int x = 0;class B {int x = 1;}class C extends B implements A {public void pX() {//System.out.println(x); //错误, 原因不明确 x//可以明确的指定 x//访问接口的 x 就使用 A.x//访问父类的 x 就使用 super.xSystem.out.println(A.x + " " + super.x);} public static void main(String[] args) {new C().pX();}}
Day22
内部类快速入门
内部类的种类
局部内部类
第七点解释:
package com.Chapter.InnerClass;public class TestInner01 { public static void main(String[] args) { Outer01 outer01 = new Outer01(); outer01.see(); }}class Outer01{ private int n1=100; public void see(){//作用域仅限于本方法体 //局部内部类本质就是一个局部变量不能有访问修饰符,只能有final //final一除不能被继承class Inner01{ int n1=200; public void see1(){//可以直接调用内部类成员 //若局部内部类的属性和外部类的属性重名是 优先调用内部的 //要是想调用外部的要用(外部类名.this.XXX) this前面没有外部类名代表是当前内部类的地址 //若有类名代表外部类的地址 System.out.println("外部n1="+n1+"内部n1="+Outer01.this.n1); System.out.println("外部的Outer01的hashcode值: "+Outer01.this); System.out.println("内部的Inner01的hashcode值: "+this); } //在类里面不能创建对象 } Inner01 inner01 = new Inner01();inner01.see1(); //局部内部类在方法中, 可以创建 Inner02 对象, 然后调用方法即可 }//在作用域外面也不能创建局部内部类对象}
匿名内部类本质
传统方式实现对象实现接口功能: 在这里调用IA里面的方法,传统的方式就是用另一个类来实现接口的方法在进行调用,但是若是如此的话,若接口不止一个,那么就要用多个类来实现接口的方法未免太过麻烦了
package com.Chapter.InnerClass;public class AnonymousInnerClass { public static void main(String[] args) { Outer02 outer02 = new Outer02(); outer02.test(); }}class Outer02{//外部类 public void test(){//在这里调用IA里面的方法,传统的方式就是用另一个类来实现接口的//方法在进行调用,但是若是如此的话,若接口不止一个,那么就要用多个类//来实现接口的方法未免太过麻烦了IA tiger1 = new tiger();//接口类型引用指向了实现接口的类的实例tiger1.see(); }}class tiger implements IA{ @Override public void see() { System.out.println("tiger实现了接口方法"); }}interface IA{//接口 public void see();//默认是抽象方法}
基于接口的匿名内部类
package com.Chapter.InnerClass;public class AnonymousInnerClass { public static void main(String[] args) { Outer02 outer02 = new Outer02(); outer02.test(); }}class Outer02 {//外部类 public void test() { //这就是匿名内部类 //应用于这个类只使用一次的场合(不是对象使用1次,tiger可以使用多次) //tiger的编译类型是IA //接口引用指向了实现该接口的类的实例 //运行类型是啥呢? /*在底层其实是这样的 Outer02$1其实是系统随机分配的名字 class Outer02$1 implements IA{ @Override public void see() { System.out.println("tiger实现了接口方法"); } } */ // jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例, 并且把地址 // 返回给 tiger //匿名内部类是只能new一次,因为你连类名都不知道,咋再次new IA tiger = new IA() { @Override public void see() { System.out.println("tiger实现了接口方法"); } };//必须有一个分号 tiger.see();//可以使用对象多次 tiger.see(); System.out.println(tiger.getClass());//测试运行类型的 }}interface IA {//接口 public void see();//默认是抽象方法}
基于类的匿名内部类
package com.Chapter.InnerClass;import com.sun.xml.internal.ws.api.ha.StickyFeature;public class AnonymousInnerClass { public static void main(String[] args) { Outer02 outer02 = new Outer02(); outer02.test(); }}class Outer02 {//外部类 public void test() { //这就是匿名内部类 //应用于这个类只使用一次的场合(不是对象使用1次,tiger可以使用多次) //tiger的编译类型是IA //接口引用指向了实现该接口的类的实例 //运行类型是啥呢? /*在底层其实是这样的 Outer02$1其实是系统随机分配的名字 class Outer02$1 implements IA{ @Override public void see() { System.out.println("tiger实现了接口方法"); } } */ // jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例, 并且把地址 // 返回给 tiger //匿名内部类是只能new一次,因为你连类名都不知道,咋再次new IA tiger = new IA() { @Override public void see1() { System.out.println("tiger实现了接口方法"); } };//必须有一个分号 tiger.see1();//可以使用对象多次 //tiger.see1(); System.out.println(tiger.getClass());//测试运行类型的 //基于类的匿名内部类 //Father father= new Father();这是直接创建对象--运行类型是Father/* class Outer$2 extends Father{ public void see() { super.see(); System.out.println("再匿名内部类里重写的see()方法"); } } */// 注意("jack") 参数列表会传递给 构造器 Father father = new Father("jack") {//这是创建匿名对象有大括号--运行类型是Outer$2 @Override public void see() { super.see(); System.out.println("再匿名内部类里重写的see()方法"); } }; father.see(); System.out.println("基于类的匿名内部类运行类型是=" + father.getClass()); }}interface IA {//接口 public void see1();//默认是抽象方法}class Father { private String name; public Father(String name) { System.out.println("传过来的名字="+name); this.name = name; } public void see() { System.out.println("你看见你爹..."); }}
匿名内部类的细节
package com.Chapter.InnerClass;public class AnonymousInnerDetail { public static void main(String[] args) { Outer03 outer03 = new Outer03(); outer03.say(); }}class Outer03{ public int n1=100; public void say() { new Person(){ @Override public void see(String str) { super.see(str); } }.see("tom"); //这样也行只调用一次see方法没有创建出对象 }}class Person{ private String name; public void see(String str){ System.out.println("Person中的方法="+str); }}
匿名内部类的应用场景
package com.Chapter.InnerClass;public class innerClassTest01 { public static void main(String[] args) { f1(new IB() { @Override public void Show() { System.out.println("hhahahahahha"); } });//只调用一次匿名生成一次对象传过去很灵活,不用再创建对象 } public static void f1(IB ib){//形参是接口类型传过来的应该是实现接口类型的对象 ib.Show(); }}interface IB{ void Show();}
package com.Chapter.InnerClass;public class innerRing { public static void main(String[] args) { Cellphone cellphone = new Cellphone(); cellphone.ring(new Bell() { @Override public void ring() { System.out.println("懒猪起床..."); } }); cellphone.ring(new Bell() { @Override public void ring() { System.out.println("起床上学了"); } }); }}interface Bell{ void ring();}class Cellphone{ public void ring(Bell bell){//接口类型形参接收实现接口的对象 System.out.println("当前运行类型是:"+bell.getClass()); bell.ring(); }}
成员内部类的细节
package com.Chapter.InnerClass;public class test01Inner { public static void main(String[] args) { //外部其他类访问内部类 // 法1 Outer04 outer04 = new Outer04(); //本质成员内部类是一个成员所以外部类对象.new XXX 可以返回该成员内部类的地址 Outer04.inner04 inner04 = outer04.new inner04(); inner04.see(); //法2 //外部其他类调用成员内部类可以提供一个公共方法来返回被创建的成员内部类的地址 Outer04.inner04 ret = outer04.ret(); ret.see(); }}class Outer04 { public int n1 = 100; private void hi() { System.out.println("外部私有hi()..."); } public class inner04 { public void see() { int n1 = 200;// Outer.this的n1 System.out.println("内部类成员n1=" + n1 + "外部类成员n1=" + Outer04.this.n1); hi();//可以直接调用 } } public inner04 ret(){//外部其他类调用成员内部类可以提供一个公共方法来返回被创建的成员内部类的地址 return new inner04(); } //外部类访问内部类要创建成员内部类对象再调用 public void deal(){ inner04 inner04 = new inner04(); inner04.see(); }}
静态内部类
package com.Chapter.InnerClass;import com.sun.xml.internal.ws.api.ha.StickyFeature;public class StaticInner { public static void main(String[] args) { //外部其他类访问静态内部类 //法一 静态内部类就可以看作为一个静态成员可以类名.成员访问,再new一下返回地址 Outer05.Inner05 inner05 = new Outer05.Inner05(); inner05.say(); //法2 接收一个静态方法返回的静态内部类的地址 Outer05.Inner05 ret = Outer05.ret(); ret.say(); }}class Outer05 { public static String name = "张三"; private static void see() { System.out.println("我是外部类的静态方法..."); } public static class Inner05 { public String name = "李四"; public void say() {//内部直接访问 外部静态成员用类名访问,非静态不能直接访问 System.out.println("内部类的name:" + name + "外部类的name:" + Outer05.name); see();//外部的static方法也可以直接调用 } } //提供一个公共方法返回静态内部类的对象的地址 public static Inner05 ret(){ return new Inner05(); }}
Day23
自定义枚举类
package com.Chapter.Enum;/ * @author 你是大吗? * version 1.0 */public class Enum01 { public static void main(String[] args) { System.out.println(Season.AUTUMN); System.out.println(Season.SPRING); }}//1. 构造器私有化防止再外面new//2.创建static四个季节对象,删除set方法,防止被改//3.加final是为了不用加载类class Season { private String name; private String detail; public final static Season SUMMER = new Season("夏天", "炎热"); public final static Season AUTUMN = new Season("秋天", "凉爽"); public final static Season WINNER = new Season("冬天", "寒冷"); public final static Season SPRING = new Season("春天", "温暖"); private Season(String name, String detail) { this.name = name; this.detail = detail; } public String getName() { return name; } public String getDetail() { return detail; } @Override public String toString() { return "Season{" + "name='" + name + '\'' + ", detail='" + detail + '\'' + '}'; }}
enum 关键字实现枚举-快速入门
package com.Chapter.Enum;/ * @author 你是大吗? * version 1.0 */public class Enum02 { public static void main(String[] args) { System.out.println(Season.SPRING); System.out.println(Season.AUTUMN); }}//1. 使用关键字 enum 替代 class//2. public static final Season SPRING = new Season("春天", "温暖") 直接使用// SPRING("春天", "温暖") 解读 常量名(实参列表)//3. 如果有多个常量(对象), 使用 ,号间隔即可//4. 如果使用 enum 来实现枚举, 要求将定义常量对象, 写在前面//5. 如果我们使用的是无参构造器, 创建常量对象, 则可以省略 ()enum Season1 { SUMMER("夏天", "炎热"),AUTUMN("秋天", "凉爽"),WINNER("冬天", "寒冷"), SPRING("春天", "温暖");//必须再最前面 private String name; private String detail;// public final static Season1 SUMMER = new Season1("夏天", "炎热");// public final static Season1 AUTUMN = new Season1("秋天", "凉爽");// public final static Season1 WINNER = new Season1("冬天", "寒冷");// public final static Season1 SPRING = new Season1("春天", "温暖"); private Season1(String name, String detail) { this.name = name; this.detail = detail; } public String getName() { return name; } public String getDetail() { return detail; } @Override public String toString() { return "Season{" + "name='" + name + '\'' + ", detail='" + detail + '\'' + '}'; }}
enum常用方法&增强for循环
1) toString:Enum 类已经重写过了, 返回的是当前对象
名,子类可以重写该方法, 用于返回对象的属性信息
2) name: 返回当前对象名(常量名) , 子类中不能重写
3) ordinal: 返回当前对象的位置号, 默认从 0 开始
4) values: 返回当前枚举类中所有的常量
5) valueOf: 将字符串转换成枚举对象, 要求字符串必须
为已有的常量名, 否则报异常!
6) compareTo: 比较两个枚举常量, 比较的就是编号!
package com.Chapter.Enum;/ * @author 你是大吗? * version 1.0 */public class Enum02 { public static void main(String[] args) { Season1 autumn = Season1.AUTUMN; System.out.println(autumn.name());//获得当前枚举常量的名字AUTUMN System.out.println(autumn.ordinal());//返回当前枚举常量的位置号 Season1[] values = Season1.values();//返回这枚举数组 //增强for循环 for(Season1 season1:values){//values获得一个对象就给season1,再打印之 System.out.println(season1); } //5) valueOf: 将字符串转换成枚举对象, 要求字符串必须 //为已有的常量名, 否则报异常! Season1 season1 = Season1.valueOf("AUTUMN"); System.out.println(season1); //6) compareTo: 比较两个枚举常量, 比较的就是编号! System.out.println(Season1.SPRING.compareTo(Season1.SUMMER)); //就和strcmp差不多 }}enum Season1 { SUMMER("夏天", "炎热"),AUTUMN("秋天", "凉爽"),WINNER("冬天", "寒冷"), SPRING("春天", "温暖");//必须再最前面 private String name; private String detail; private Season1(String name, String detail) { this.name = name; this.detail = detail; } public String getName() { return name; } public String getDetail() { return detail; } @Override public String toString() { return "Season{" + "name='" + name + '\'' + ", detail='" + detail + '\'' + '}'; }}
enum实现接口
1) 使用 enum 关键字后, 就不能再继承其它类了, 因为 enum 会隐式继承 Enum, 而 Java 是单继承机制。
2) 枚举类和普通类一样, 可以实现接口, 如下形式。
enum 类名 implements 接口 1, 接口 2{}
package com.Chapter.Enum;/ * @author 你是大吗? * version 1.0 */public class interfaceEnum { public static void main(String[] args) { Music.PlayMusic.play(); //PlayMusic是静态的不用new }}interface IA{ public void play();}enum Music implements IA{ PlayMusic; @Override public void play() { System.out.println("播放音乐"); }}
注解
- @Override: 限定某个方法, 是重写父类方法, 该注解只能用于方法
- @Deprecated: 用于表示某个程序元素(类, 方法等)已过时
- @SuppressWarnings: 抑制编译器警告
匿名内部类练习题
package com.Chapter.Enum;/ * @author 你是大吗? * version 1.0 */public class innerClass { public static void main(String[] args) { TestCal testCal = new TestCal(); // testCal.TestWork(new Cal() {//既是匿名内部类又是对象 @Override public double work(double n1, double n2) { return n1+n2; } },18,1); }}interface Cal{//接口 double work(double n1,double n2);}class TestCal{ //接口类性的引用作为形参,根据运行类型去调用work方法 public void TestWork(Cal cal,double n1,double n2){ double result=cal.work(n1,n2); System.out.println("结果是:"+result); }}
匿名内部类练习题
题目:
/
匿名内部类面试题:
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
/
package com.Chapter.Enum;/ * @author 你是大吗? * version 1.0 */public class CSDNinnerClass { public static void main(String[] args) { Outer.Method().show();//返回匿名内部类的地址.Show再调用Show方法 }}interface Inter { void show();}class Outer { public static Inter Method() {//静态方法 return new Inter() {//返回匿名内部类的地址 @Override public void show() { System.out.println("hello world"); } }; }}/*匿名内部类面试题:按照要求,补齐代码interface Inter { void show(); }class Outer { //补齐代码 }class OuterDemo {public static void main(String[] args) { Outer.method().show(); }}要求在控制台输出”HelloWorld”*/
交通方式题*
package com.Chapter.Enum;/ * @author 你是大吗? * version 1.0 */public class Tang { public static void main(String[] args) { //默认是走陆路 Person tangs = new Person("唐僧", new Horses()); //传过去实现了运输方式的对象根据运行类型调用work()方法 tangs.Boating(); tangs.Common(); tangs.AircraftIng(); }}interface Vehicles{//接口 void work();}class Horses implements Vehicles{ @Override public void work() { System.out.println("一般就是走陆路。。。"); }}class Aircraft implements Vehicles{ @Override public void work() { System.out.println("有火焰山坐飞机..."); }}class Boats implements Vehicles{ @Override public void work() { System.out.println("有河就走水路...."); }}class VehicleFactory{//车辆工具厂类返回两个实现了接口功能的对象 //静态的类加载的时候才创建一次 //懒汉式 public static Horses horses=new Horses(); private VehicleFactory() {//构造器私有化不让在外面创建对象 } public static Horses GetHorses(){ return horses; } public static Boats GetBoats(){ return new Boats(); } public static Aircraft GetAircraft(){ return new Aircraft(); }} class Person{ private String name; private Vehicles vehicles;//接口功能属性 public Person(String name, Vehicles vehicles) { // this.name = name; this.vehicles = vehicles; //vehicles.work();//构造器初始化默认调用的交通方式 } //这里定义两个方法,获得两个交通方式 public void Common(){ //若vehicles当前运行类型是Horses就是不执行if直接执行 if(!(vehicles instanceof Horses)){ //向上转型 接口引用指向实现了接口的对象的实例 vehicles=VehicleFactory.GetHorses(); //根据工厂类来返回Horses对象 } vehicles.work();//结合运行类型来调用work(); } public void Boating(){ //若vehicles当前运行类型是Boats就是不执行if直接执行 if(!(vehicles instanceof Boats)){ //向上转型 接口引用指向实现了接口的对象的实例 vehicles=VehicleFactory.GetBoats(); //根据工厂类来返回Boats对象 } vehicles.work();//结合运行类型来调用work(); } public void AircraftIng(){ if(!(vehicles instanceof Aircraft)){ //向上转型 接口引用指向实现了接口的对象的实例 vehicles=VehicleFactory.GetAircraft(); //根据工厂类来返回Aircraft对象 } vehicles.work(); } }
枚举练习题
package com.Chapter.Enum;/ * @author 你是大吗? * version 1.0 */public class practical06 { public static void main(String[] args) { //类名.枚举常量 Color green = Color.GREEN; green.Show(); System.out.println(green.name());//~ System.out.println(green);打印枚举常量的名字 switch(green){ case GREEN: System.out.println("匹配到绿色"); break; case BLUE: System.out.println("匹配到蓝色"); break; case BLACK: System.out.println("匹配到黑色"); break; case RED: System.out.println("匹配到红色"); break; case YELLOW: System.out.println("匹配到黄色"); break; } }}enum Color implements IO{ RED(255,0,0),BLUE(0,0,255), BLACK(0,0,0),YELLOW(255,255,0), GREEN(0,255,0); public int redValue; public int greenValue; public int blueValue; Color(int redValue, int greenValue, int blueValue) { this.redValue = redValue; this.greenValue = greenValue; this.blueValue = blueValue; } public int getRedValue() { return redValue; } public int getGreenValue() { return greenValue; } public int getBlueValue() { return blueValue; } @Override public void Show() { System.out.println("元素值:"+redValue+","+greenValue+","+blueValue); }}interface IO{ void Show();}
Day24
异常
//如果程序员, 认为一段代码可能出现异常/问题, 可以使用 try-catch 异常处理机制来解决
//从而保证程序的健壮性
//将该代码块->选中->快捷键 ctrl + alt + t -> 选中 try-catch
//6. 如果进行异常处理, 那么即使出现了异常, 程序可以继续执行
package com.Chapter.Usual;/ * @author 你是大吗? * version 1.0 */public class usual { public static void main(String[] args) { int n1=100; int n2=0; //将该代码块->选中->快捷键 ctrl + alt + t -> 选中 try-catch int result= 0; try { result = n1/n2; } catch (Exception e) { System.out.println(e.getMessage());//打印异常信息 } //6. 如果进行异常处理, 那么即使出现了异常, 程序可以继续执行 System.out.println("========"); }}
异常介绍
异常体系图:
五大常见异常
1) NullPointerException 空指针异常
2) ArithmeticException 数学运算异常
3) ArrayIndexOutOfBoundsException 数组下标越界异常
4) ClassCastException 类型转换异常
5) NumberFormatException 数字格式不正确异常[]
package com.Chapter.Usual;/ * @author 你是大吗? * version 1.0 */public class Exception01 { public static void main(String[] args) {// int []array={1,2,3};// for(int i:array){// System.out.println(i);// }// //ArrayIndexOutOfBoundsException// System.out.println(array[3]);//3下标就越界了// //空指针异常// A b = new B();// B b1=(B)b;// C c1=(C)b;//类型转换异常// //ClassCastException //NumberFormatException String name ="秦琼"; int n=Integer.parseInt(name); System.out.println(n); }}class A {}class B extends A{}class C extends A{}
编译时异常
异常处理
try-catch异常处理
package com.Chapter.Usual;/ * @author 你是大吗? * version 1.0 */public class ExceptionDetail01 { public static void main(String[] args) { try { //有了异常try块就不执行了,不会进入catch块,没有就执行,故进入catch()块 int n1=10; int n2=0; int res=n1/n2; System.out.println("结果="+res); } catch (Exception e) { //相关处理 System.out.println("异常信息:="+e.getMessage()); }finally { //不管有没有异常finally块都执行 ,可以完成一些释放资源的操作 System.out.println("finally代码块执行..."); } }}
package com.Chapter.Usual;/ * @author 你是大吗? * version 1.0 */public class ExceptionDetail01 { public static void main(String[] args) { try { //有了异常try块就不执行了,不会进入catch块,没有就执行,故进入catch()块 //1.如果 try 代码块有可能有多个异常 //2.可以使用多个 catch 分别捕获不同的异常, 相应处理 //3.要求子类异常写在前面, 父类异常写在后面 Person tom = new Person("tom"); tom = null; System.out.println(tom.name); int n1 = 10; int n2 = 0; int res = n1 / n2; System.out.println("结果=" + res); } catch (NullPointerException e) { System.out.println("空指针异常...."+e.getMessage()); } catch ( ArithmeticException e) { System.out.println("算数异常..." + e.getMessage()); } catch (Exception e) { //相关处理 // System.out.println("异常信息:=" + e.getMessage()); } finally { //不管有没有异常finally块都执行 ,可以完成一些释放资源的操作 System.out.println("finally代码块执行..."); } }}class Person { public String name; public Person(String name) { this.name = name; }}
异常练习题
异常小结:
try-catch最佳实践 无限输入判断是不是整数
如果用户输入的不是一个整数, 就提示他反复输入, 直到输入一个整数为止
package com.Chapter.Usual;import java.util.Scanner;/ * @author 你是大吗? * version 1.0 */public class ExceptionPractical { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int num; while(true){ try { System.out.print("请输入一个整数:"); //scanner.next()是获得第 一个字符串 //Integer.parseInt是把数字字符串转换为整数 num=Integer.parseInt(scanner.next()); break;//若上面转换成功就没有问题可以执行到break } catch (NumberFormatException e) { System.out.println("输入有误,请重新输入:"); } } System.out.println("转换完成="+num); }}
throws 异常处理
throws异常细节
自定义异常
即把自定义异常做成 运行时异常, 好处是, 我们可以使用默认的处理机制
package com.Chapter.Usual;/ * @author 你是大吗? * version 1.0 */public class CustomException { public static void main(String[] args) { int age=1000; if(!(age>0&&age<150)){ //抛出自定义异常 throw new AgeException("年龄输入错误:1~150..."); } System.out.println("年龄正确..."); }}//继承运行时异常类 class AgeException extends RuntimeException{ public AgeException(String message) { super(message); }}
异常练习题1
package com.Chapter.Usual;/ * @author 你是大吗? * version 1.0 */public class ExceptionPractical01 { public static void main(String[] args) { try { if(args.length!=2){ throw new ArrayIndexOutOfBoundsException("元素个数不对..."); //抛出异常,若是不catch()就是默认处理 }//继续向下执行就是上面没有发生异常 //这里可能发生类型转换异常 int n1=Integer.parseInt(args[0]); int n2=Integer.parseInt(args[1]); //这里可能发生分母为0异常 double res =cal(n1,n2); System.out.println("res="+res);// } catch (ArrayIndexOutOfBoundsException e) {// System.out.println(e.getMessage());//系统封装成了异常对象e }catch (NumberFormatException e){ System.out.println("类型转换异常..."); }catch (ArithmeticException e){ System.out.println("分母为0..."); } } public static double cal(int n1,int n2){ return n1/n2; }}
Day 25
包装类
1) 针对八种基本数据类型相应的引用类型—包装类
2) 有了类的特点, 就可以调用类中的方法。
拆箱与装箱
package com.Chapter.Chapter12;/ * @author 你是大吗? * version 1.0 */public class Integer01 { public static void main(String[] args) { //手动装箱拆箱 int n1 = 100; Integer integer1 = new Integer(n1); Integer integer2 = Integer.valueOf(n1); int i1 = integer1.intValue();//拆箱 //自动装箱拆箱 int n2 = 10; Integer integer3=n2;//底层使用的是 Integer.valueOf(n2) int i2=integer3;//底层使用:integer1.intValue() }}
练习题
StringInteger 转换方式
package com.Chapter.Chapter12;/ * @author 你是大吗? * version 1.0 */public class Integer_String { public static void main(String[] args) { // 以 Integer 和 String 转换为例, Integer i=10;//自动装箱 //法1 String str1=i+"";//i是没有变化的 //法2 String str2 = i.toString(); //将整型包装类转换为字符串 //法3 String str3 = String.valueOf(i); //整形包装类的i转换为字符串 //String -->Integer String str="124"; //法1 Integer integer1=Integer.valueOf(str); //将字符串转换为Integer //法2 Integer integer2=Integer.parseInt(str); //先转换为整形再自动装箱为了Integer类型 //法3 Integer integer3 = new Integer(str); System.out.println("ing......."); System.out.println("========================================"); System.out.println(Integer.MIN_VALUE); //返回最小值 System.out.println(Integer.MAX_VALUE);//返回最大值 System.out.println(Character.isDigit('a'));//判断是不是数字 System.out.println(Character.isLetter('a'));//判断是不是字母 System.out.println(Character.isUpperCase('a'));//判断是不是大写 System.out.println(Character.isLowerCase('a'));//判断是不是小写 System.out.println(Character.isWhitespace('a'));//判断是不是空格 System.out.println(Character.toUpperCase('a'));//转成大写 System.out.println(Character.toLowerCase('A'));//转成小写 }}
integer面试题
package com.Chapter.Chapter12;/ * @author 你是大吗? * version 1.0 */public class interview01 { public static void main(String[] args) { Integer i = new Integer(1); Integer j = new Integer(1); System.out.println(i == j); //False//所以, 这里主要是看范围 -128 ~ 127 就是直接返回/*老韩解读//1. 如果 i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回//2. 如果不在 -128~127,就直接 new Integer(i)public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}*/ Integer m = 1; //底层 Integer.valueOf(1); -> 阅读源码 Integer n = 1;//底层 Integer.valueOf(1); System.out.println(m == n); //T//所以, 这里主要是看范围 -128 ~ 127 就是直接返回//, 否则, 就 new Integer(xx); Integer x = 128;//底层 Integer.valueOf(1); Integer y = 128;//底层 Integer.valueOf(1); System.out.println(x == y);//False }}
String类
package com.Chapter.Chapter12;import java.io.Serializable;/ * @author 你是大吗? * version 1.0 */public class StringDetail01 { public static void main(String[] args) { String name="tom";//private final char value[]; //本质还是用字符数组存放 //String是final的不能被继承 //final在这里的意思是 value这个指针变量里面的值不能被修改 //也就是指向不能变,但是单个字符是可以改变的 final char [] array={'a','b','c'}; char [] array1 ={'b','d'}; //array=array1;这是不对的把final去掉是对的 //String 类实现了接口 Serializable【String 可以串行化:可以在网络传输】// 接口 Comparable [String 对象可以比较大小] }}
创建 String 对象的两种方式
package com.Chapter.Chapter12;/ * @author 你是大吗? * version 1.0 */public class StringDetail02 { public static void main(String[] args) { String str1="hello"; String str2 = new String("hello"); }}
内存分布图:
测试题
1
2
3
4
5
6
7
String 类的常见方法一览
package com.Chapter.Chapter12;import com.sun.xml.internal.ws.api.ha.StickyFeature;/ * @author 你是大吗? * version 1.0 */public class StringDetail02 { public static void main(String[] args) {String a="hello";a=a.substring(1,4); System.out.println(a); // 4.indexOf 获取字符在字符串对象中第一次出现的索引, 索引从 0 开始, 如果找不到, 返回-1 String s1 = "wer@terwe@g"; int index = s1.indexOf('@'); System.out.println(index);// 3 System.out.println("weIndex=" + s1.indexOf("we"));//0// 5.lastIndexOf 获取字符在字符串中最后一次出现的索引, 索引从 0 开始, 如果找不到, 返回-1 s1 = "wer@terwe@g@"; index = s1.lastIndexOf('@'); System.out.println(index);//11 System.out.println("ter 的位置=" + s1.lastIndexOf("ter"));//4// 3.concat 拼接字符串 String s7 = "宝玉"; s7 = s7.concat("林黛玉").concat("薛宝钗").concat("together"); System.out.println(s7);//宝玉林黛玉薛宝钗 together// 4.replace 替换字符串中的字符 s7 = "宝玉 and 林黛玉 林黛玉 林黛玉";//在 s1 中, 将 所有的 林黛玉 替换成薛宝钗// 老韩解读: s1.replace() 方法执行后, 返回的结果才是替换过的.// 注意对 s1 没有任何影响 String s11 = s7.replace("宝玉", "jack"); System.out.println(s7);//宝玉 and 林黛玉 林黛玉 林黛玉 System.out.println(s11);//jack and 林黛玉 林黛玉 林黛玉// 5.split 分割字符串, 对于某些分割字符, 我们需要 转义比如 | \\等 String poem = "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦";//老韩解读:// 1. 以 , 为标准对 poem 进行分割 , 返回一个数组// 2. 在对字符串进行分割时, 如果有特殊字符, 需要加入 转义符 \ String[] split = poem.split(","); poem = "E:\\aaa\\bbb"; split = poem.split("\\\\"); System.out.println("==分割后内容==="); for (int i = 0; i < split.length; i++) { System.out.println(split[i]); }// s = "happy";// char[] chs = s.toCharArray();// for (int i = 0; i < chs.length; i++) {// System.out.println(chs[i]);// } // // 7.compareTo 比较两个字符串的大小, 如果前者大,// 则返回正数, 后者大, 则返回负数, 如果相等, 返回 0// 老韩解读// (1) 如果长度相同, 并且每个字符也相同, 就返回 0// (2) 如果长度相同或者不相同, 但是在进行比较时, 可以区分大小// 就返回 if (c1 != c2) {// return c1 - c2;// }// (3) 如果前面的部分都相同, 就返回 str1.len - str2.len String a1 = "jcck";// len = 3 String b = "jack";// len = 4 System.out.println(a.compareTo(b)); // 返回值是 'c' - 'a' = 2 的值 //格式化输出 String s22="张安"; int age=10; char gender='男'; double score=99.999; String str= String.format("名字%s 年龄%d 性别%c 分数%.2f",s22,age,gender,score); System.out.println(str); }}
StringBuffer 类
特点
//1. StringBuffer 的直接父类 是 AbstractStringBuilder
//2. StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化
//3. 在父类中 AbstractStringBuilder 有属性 char[] value,不是 final
// 该 value 数组存放 字符串内容, 引出存放在堆中的
//4. StringBuffer 是一个 final 类, 不能被继承
//5. 因为 StringBuffer 字符内容是存在 char[] value, 所有在变化(增加/删除)
// 不用每次都更换地址(即不是每次创建新对象), 所以效率高于 String
这是构造器字符串长度+16个长度,就是默16个字符空间
String VS StringBuffer
Stringbufferd的父类构造器中的存放字符的字符数组:
String存放字符的字符数组:
以上是二者区别画张图来详细分析:
String 和 StringBuffer 相互转换
String str1= "hello"; //String-->StringBuffer //1.构造器法 StringBuffer stringBuffer = new StringBuffer(str1); //2.append方法 StringBuffer stringBuffer2 = new StringBuffer(); stringBuffer2=stringBuffer2.append(str1); //""+连接串 //StringBuffer-->String //1.toString StringBuffer hello = new StringBuffer("hello"); String s = hello.toString(); //2构造器 String s1 = new String(hello);
StringBuffer 类常见方法【增删查改】
StringBuffer stringBuffer = new StringBuffer("秦叔宝"); //StringBuffer 类常见方法 //1.append System.out.println("连接之前:="+stringBuffer); StringBuffer stringBuffer1 = stringBuffer.append(":秦琼").append("脚踏黄河两岸").append(19); System.out.println("连接之后:="+stringBuffer1);//2.delete StringBuffer delete = stringBuffer1.delete(0, 2); System.out.println("删除之后:"+delete);//[0,2) //连接之后:=秦叔宝:秦琼脚踏黄河两岸19 //删除之后:宝:秦琼脚踏黄河两岸19//3.(replace)改 StringBuffer rePlace1 = stringBuffer1.replace(0, 2, "罗通"); System.out.println("修改之后="+rePlace1);//[0,3) //修改之后=罗通秦琼脚踏黄河两岸19//4.查找指定的子串在字符串第一次出现的索引, 如果找不到返回-1 int index = stringBuffer1.indexOf("秦琼"); System.out.println("第一次出现的位置是:="+index); //修改之后=罗通秦琼脚踏黄河两岸19 //第一次出现的位置是:=2 //5.insert 插入 StringBuffer insert1 = stringBuffer1.insert(3, "罗通"); System.out.println("插入之后="+insert1);//下标为3的位置插入其后向后挪 //6.长度 System.out.println(stringBuffer1.length());
StringBuffer 类课堂测试题1
package com.Chapter.Chapter12;/ * @author 你是大吗? * version 1.0 */public class StringBuffer01 { public static void main(String[] args) { String str = null;// ok StringBuffer sb = new StringBuffer(); //ok sb.append(str);//需要看源码 , 底层调用的是 AbstractStringBuilder 的 appendNull System.out.println(sb.length());//4 /* int c = count; ensureCapacityInternal(c + 4); final char[] value = this.value; value[c++] = 'n'; value[c++] = 'u'; value[c++] = 'l'; value[c++] = 'l'; count = c; return this; *///所以打印null System.out.println(sb);//null//下面的构造器, 会抛出 NullpointerException StringBuffer sb1 = new StringBuffer(str);//看底层源码 super(str.length() + 16); System.out.println(sb1);//null.length肯定不对抛出异常 }}
StringBuffer 类课堂测试题2
/ * @author 你是大吗? * version 1.0 */public class Stringbufferpractical02 { public static void main(String[] args) {// 输入商品名称和商品价格, 要求打印效果示例, 使用前面学习的方法完成:// 商品名 商品价格// 手机 123,564.59 //比如 价格 3,456,789.88// 要求: 价格的小数点前面每三位用逗号隔开, 在输出 StringBuffer stringBuffer = new StringBuffer("123345678.9"); //法一// for (int i = stringBuffer.lastIndexOf("."); i >3 ; i-=3) {// stringBuffer.insert(i-3, ",");//i=3时就在0的位置上添加了是不对的// } //法2 for (int i = stringBuffer.lastIndexOf(".")-3; i >0 ; i-=3) { stringBuffer.insert(i, ",");//直接想.后面第三个位置上插入,i>0就行 } System.out.println("插入之后="+stringBuffer); }}
StringBuilder 类
StringBuilder 的方法, 没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用StringBuilder
String、 StringBuffer 和 StringBuilder 的比较
package com.Chapter.Chapter12;/ * @author 你是大吗? * version 1.0 */public class TestStr { public static void main(String[] args) { //String long startTime = 0l; long endTime = 0l; String str = ""; startTime = System.currentTimeMillis(); for (int i = 0; i < 80000; i++) { str += String.valueOf(i); } endTime = System.currentTimeMillis(); System.out.println("String--花费时间="+(endTime-startTime)+"毫秒"); //StringBuffer StringBuffer stringBuffer = new StringBuffer(""); startTime = System.currentTimeMillis(); for (int i = 0; i < 80000; i++) { stringBuffer.append(String.valueOf(i)); //拼接 } endTime = System.currentTimeMillis(); System.out.println("StringBuffer--花费时间="+(endTime-startTime)+"毫秒"); //StringBuffer StringBuilder stringBuilder = new StringBuilder(""); startTime = System.currentTimeMillis(); for (int i = 0; i < 80000; i++) { stringBuilder.append(String.valueOf(i)); //拼接 } endTime = System.currentTimeMillis(); System.out.println("StringBuilder--花费时间="+(endTime-startTime)+"毫秒"); }}
Math八大常用方法(含求a-b之间的随机数)
package com.Chapter.Chapter12;/ * @author 你是大吗? * version 1.0 */public class Marh01 { public static void main(String[] args) { //1.abs int n1=Math.abs(-19); System.out.println("求绝对值"+n1);//19 //2.pow 求幂 double n2=Math.pow(2,8); System.out.println("x的y次幂="+n2);//256 //3.ceil 向上取整,返回>=该参数的最小整数(转成 double);ceil天花板 double n3=Math.ceil(3.8); System.out.println("向上取整="+n3);//4.0 //4.floor 向下取整, 返回<=该参数的最大整数(转成 double) double n4=Math.floor(3.8); System.out.println("向下取整="+n4);//3.0 //5.round 四舍五入 Math.floor(该参数+0.5) double n5=Math.round(2.2); System.out.println("四舍五入="+n5); //6.sqrt 求开方 double n6 = Math.sqrt(9.0); System.out.println(n6);//3.0 //7.random 求随机数 // random 返回的是 0 <= x < 1 之间的一个随机小数// for (int i = 0; i < 10; i++) {// System.out.print((int)(Math.random()*100)+" ");// } //求a-b之间的随机数 // Math.random() * (b-a) 返回的就是 0 <= 数 <= b-a // (1) (int)(a) <= x <= (int)(a + Math.random() * (b-a +1) ) for (int i = 0; i < 10; i++) { System.out.print((int)(2+Math.random()*(7-2+1))+" "); } //让产生的随机数去乘6+2(a)再强转// 8.max , min 返回最大值和最小值 int min = Math.min(1, 9); int max = Math.max(45, 90); System.out.println("min=" + min); System.out.println("max=" + max); }}