淘宝联盟优惠券网站建设,品牌网站建设必在大蝌蚪,中国世界排名前500大学,wordpress移动版样式Java零基础入门6.0Java系列第六章1. 面向对象综合练习1.1 文字版格斗游戏参数占位#xff0c;格式化输出回顾关于printf和print和println的区别1.2 对象数组练习1.2.1 练习一1.2.2 练习二1.2.3 练习三1.2.4 练习四1.3 键盘录入回顾1.4 复杂对象数组练习1.4.1 复杂练习一1.4.2 …
Java零基础入门6.0Java系列第六章1. 面向对象综合练习1.1 文字版格斗游戏参数占位格式化输出回顾关于printf和print和println的区别1.2 对象数组练习1.2.1 练习一1.2.2 练习二1.2.3 练习三1.2.4 练习四1.3 键盘录入回顾1.4 复杂对象数组练习1.4.1 复杂练习一1.4.2 复杂练习二2. API:应用程序编程接口2.1 使用帮助文档3. 字符串String3.1 创建String对象的两种方式3.2 字符串的比较3.3 字符串练习3.3.1 练习一用户登录3.3.2 练习二 ctrlaltv 自动生成左边赋值3.3.3 练习三字符串拼接和反转3.3.4 练习四3.3.5 练习五3.4 StringBuilder3.4.1 StringBuilder构造方法3.4.2 StringBuilder常用方法3.4.3 链式编程3.4.4 StringJoiner3.4.5 字符串原理扩展底层原理1和2字符串原理扩展底层原理3字符串拼接的底层原理扩展底层原理5StringBuilder提高效率原理扩展底层原理5:StringBuilder源码分析ctrl n IDEA快捷键 出现搜索界面3.4.6 字符串综合练习4. 集合4.1 ArrayList 集合之一4.2 集合综合练习4.2.1 添加字符串和整数遍历4.2.2 基本数据类型的包装类4.2.3 添加学生对象并遍历4.2.4 添加用户对象并判断是否存在4.2.5 添加手机对象并返回要求的数据5. 学生管理系统5.1 学生管理系统升级版6. 面向对象进阶6.1 static6.1.1 static-静态变量6.1.2 static-静态方法和工具静态方法工具类6.1.3 static-注意事项6.1.4 重新认识main方法6.2 继承6.2.1 封装6.2.2 继承的描述6.2.3 继承的特点6.2.4 子类继承父类的特性6.2.5 终端的jps和jhsdb hsdb6.2.6 继承中成员变量和成员方法的访问特点继承成员变量继承成员方法6.2.6 继承中的构造方法6.2.7 this、super关键字总结6.3 认识多态6.3.1 多态中调用成员的特点6.3.2 多态的优势和弊端6.3.3 instanceof 判断是不是相应类型6.3.4 多态综合练习6.4 包和 final6.4.1 包6.4.2 final 与static类似的关键字6.5 权限修饰符和代码块6.5.1 权限修饰符6.5.2 代码块6.6 抽象类和抽象方法6.7 接口6.7.1 接口的细节成员特点和各种接口的关系6.7.2 接口和抽象类案例6.7.3 接口的新增方法jdk8以后接口中新增的默认方法jdk8以后接口中新增的静态方法jdk9新增的私有方法6.7.4 接口应用6.7.5 适配器设计模型6.8 初始内部类6.8.1 成员内部类6.8.2 静态内部类6.8.3 局部内部类6.8.4 匿名内部类Java系列第六章
1. 面向对象综合练习
1.1 文字版格斗游戏 1.简单版 User类包
package test3;import java.util.Random;public class User {private String name;private int blood;private char gender;private String face;//长相随机String[] boyfaces {风流俊雅, 气宇轩昂, 相貌英俊, 五官端正, 相貌平平, 一塌糊涂, 面目狰狞};String[] girlfaces {美奂绝伦, 沉鱼落雁, 婷婷玉立, 身材娇好, 相貌平平, 相貌简陋, 惨不忍睹};//attack攻击描述:String[] attacks_desc {%s使出了一招【背心钉】转到对方的身后一掌向%s背心的灵台穴拍去。,%s使出了一招【游空探爪】飞起身形自半空中变掌为抓锁向%s。,%s大喝一声身形下伏一招【劈雷坠地】捶向%s双腿。,%s运气于掌一瞬间掌心变得血红一式【掌心雷】推向%s。,%s阴手翻起阳手跟进一招【没逛拦】结结实实的挺向%s。,%s上步抢身招中套招一招【劈挂连环】连环攻向%s};//injured受伤描述:String[] injureds_desc {结果%s退了半步毫发无损,结果给%s造成一处瘀伤,结果一击命中%s痛得弯下腰,结果%s痛苦地闷哼了一声显然受了点内伤,结果%s摇摇晃晃一跤摔倒在地,结果%s脸色一下变得惨白连退了好几步,结果『轰』的一声%s口中鲜血狂喷而出,结果%s一声惨叫像滩软泥般塌了下去,};public User() {}public User(String name, int blood, char gengder) {this.name name;this.blood blood;this.gender gender;//随机长相setFace(gender);}public char getGender() {return gender;}public void setGender(char gender) {this.gender gender;}public String getFace() {return face;}public void setFace(char gender) {Random r new Random();//长相随机if (gender 男) {//从boyfaces里面随机长相int index r.nextInt(boyfaces.length);this.face boyfaces[index];} else if (gender 女) {//从girlfaces里面随机长相int index r.nextInt(girlfaces.length);this.face girlfaces[index];} else {this.face 面目狰狞;}}public String getName() {return name;}public void setName(String name) {this.name name;}public int getBlood() {return blood;}public void setBlood(int blood) {this.blood blood;}//定义一个方法用于攻击别人//思考谁攻击谁//r1.攻击(r2)//方法的调用者去攻击参数public void attack(User user) {Random r new Random();int index r.nextInt(attacks_desc.length);String KungFu attacks_desc[index];//输出一个攻击的效果System.out.printf(KungFu,this.getName(),user.getName());System.out.println();//计算造成的伤害int hurt r.nextInt(20) 1;//修改一下挨揍的人血量//剩余血量int remainBoold user.getBlood() - hurt;//对剩余血量做一个验证如果为负数了就修改为0remainBoold remainBoold 0 ? 0 : remainBoold;//修改一下挨揍的人血量user.setBlood(remainBoold);//受伤的描述//血量90 0 索引的描述//80 ~ 90 1索引的描述//70 ~ 80 2索引的描述// 60 ~ 70 3索引的描述// 40 ~ 60 4索引的描述// 20 ~ 40 5索引的描述// 10 ~ 20 6索引的描述// 小于10的 7索引的描述if(remainBoold 90){System.out.printf(injureds_desc[0],user.getName());}else if(remainBoold80remainBoold90){System.out.printf(injureds_desc[1],user.getName());}else if(remainBoold70remainBoold80){System.out.printf(injureds_desc[2],user.getName());}else if(remainBoold60remainBoold70){System.out.printf(injureds_desc[3],user.getName());}else if(remainBoold40remainBoold60){System.out.printf(injureds_desc[4],user.getName());}else if(remainBoold20remainBoold40){System.out.printf(injureds_desc[5],user.getName());}else if(remainBoold10remainBoold200){System.out.printf(injureds_desc[6],user.getName());}else{System.out.printf(injureds_desc[7],user.getName());}System.out.println();}public void showRoleInfo() {System.out.println(姓名为 getName());System.out.println(血量为 getBlood());System.out.println(性别为 getGender());System.out.println(长相为 getFace());}
}
GameTest类包
package test3;public class GameTest {public static void main(String[] args) {// 1. 创建第一个角色User u1 new User(麻瓜,100,男);//2.创建第二个角色User u2 new User(小老板,100,男);//展示角色信息u1.showRoleInfo();System.out.println(------------------------);u2.showRoleInfo();System.out.println(------------------------);//3.开始格斗 回合制游戏while(true){//u1 开始攻击u2u1.attack(u1);//判断u2的剩余血量if(u2.getBlood()0){System.out.println(u1.getName()K.O了u2.getName());break;}//u2开始攻击u1u2.attack(u1);if(u1.getBlood()0){System.out.println(u2.getName()K.O了u1.getName());break;}}}
} 参数占位格式化输出回顾
public static void main(String[] args) {//两部分参数//第一部分参数:要输出的内容%s占位)// 第二部分参数:填充的数据System.out.printf(%s你好啊%s,张三,李四);//但是printf没有换行效果System.out.println();System.out.printf(你好啊%s,李四);}关于printf和print和println的区别
print为一般输出同样不能保留精度格式转化也不能换行输出printf常用于格式转换但需要注意不是换行输出只用于精度转换println为换行输出不能用于格式转换
1.2 对象数组练习
1.2.1 练习一 Goods 类包
package test4;public class Goods {private String id;private String name;private double price;private int count;public Goods(){}public Goods(String id,String name,double price, int count){this.id id;this.name name;this.price price;this.count count;}public String getId() {return id;}public void setId(String id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public double getPrice() {return price;}public void setPrice(double price) {this.price price;}public int getCount() {return count;}public void setCount(int count) {this.count count;}
}
GoodsTest 引入执行
package test4;public class GoodsTest {public static void main(String[] args) {//1.创建一个数组Goods[] arr new Goods[3];//2.创建三个商品//快捷键 ctrlp 把方法所对应的参数所展示Goods g1 new Goods(001,华为p40,599.0,100);Goods g2 new Goods(002,保温杯,297,50);Goods g3 new Goods(003,洗衣机,10000,500);//3.把商品添加到数组中arr[0]g1;arr[1]g2;arr[2]g3;//4.遍历for (int i 0; i arr.length; i) {// i 索引 arr[i] 元素Goods goods arr[i];System.out.println(goods.getId(),goods.getName(),goods.getPrice(),goods.getCount());}}
} 1.2.2 练习二 Car的javabeen包
package test5;public class Car {private String brand;//品牌private int price;//价格private String color;//颜色public Car(){}public Car(String brand, int price, String color) {this.brand brand;this.price price;this.color color;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand brand;}public int getPrice() {return price;}public void setPrice(int price) {this.price price;}public String getColor() {return color;}public void setColor(String color) {this.color color;}
}CarTest
package test5;import java.util.Scanner;public class CarTest {public static void main(String[] args) {//1.创建一个数组用来存3个汽车对象Car[] arr new Car[3];//2.创建汽车对象数据来自于键盘录入//如果把Car c new Car();放在循环的外面那么对象就只有一辆车//此时下面循环就对同一辆车的属性进行修改而不是创建新的属性//所以此创建对象的代码不能写在循环的外面必须写在循环里面Scanner sc new Scanner(System.in);for (int i 0; i arr.length; i) {//创建汽车对象Car c new Car();//录入品牌System.out.println(请输入汽车的品牌);String brand sc.next();c.setBrand(brand);//录入价格System.out.println(请输入汽车的价格);int price sc.nextInt();c.setPrice(price);//录入颜色System.out.println(请输入汽车的颜色);String color sc.next();c.setColor(color);//把汽车对象添加到数组当中arr[i]c;}//3.遍历数组for (int i 0; i arr.length; i) {Car car arr[i];System.out.println(car.getBrand(),car.getPrice(),car.getColor());}}
} 1.2.3 练习三 Phone的javabeen包
package test6;public class Phone {private String brand;//品牌private int price;//价格private String color;//颜色public Phone(){}public Phone(String brand,int price,String color){this.brand brand;this.price price;this.color color;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand brand;}public int getPrice() {return price;}public void setPrice(int price) {this.price price;}public String getColor() {return color;}public void setColor(String color) {this.color color;}
}PhoneTest
package test6;public class PhoneTest {public static void main(String[] args) {//1.创建一个数组Phone[] arr new Phone[3];//2.创建手机的对象Phone p1 new Phone(xiaomi,1999,white);Phone p2 new Phone(huawei,4999,blue);Phone p3 new Phone(meizhu,2999,red);//3.把手机对象添加到数组当中arr[0]p1;arr[1]p2;arr[2]p3;//4.获取三部手机的平均价格int sum 0;for (int i 0; i arr.length; i) {//i索引 arr[i]元素手机对象Phone phone arr[i];sum sum phone.getPrice();}//5.求平均值double avg sum*1.0/arr.length;System.out.println(avg);}
}1.2.4 练习四 GilFriend的javabeen包
package test7;public class GirlFriend {private String name;//姓名private int age; //年龄private String gender;//性别private String hobby;//爱好public GirlFriend() {}public GirlFriend(String name, int age, String gender, String hobby) {this.name name;this.age age;this.gender gender;this.hobby hobby;}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 getGender() {return gender;}public void setGender(String gender) {this.gender gender;}public String getHobby() {return hobby;}public void setHobby(String hobby) {this.hobby hobby;}
}
GirlFriendTest
package test7;public class GirlFriendTest {public static void main(String[] args) {//1.定义数组存入女朋友的对象GirlFriend[] arr new GirlFriend[4];//2.创建女朋友的对象GirlFriend gf1 new GirlFriend(小老板,22,man,do the game);GirlFriend gf2 new GirlFriend(麻瓜,24,man,van the game);GirlFriend gf3 new GirlFriend(马捞C,30,man,乖乖站好);GirlFriend gf4 new GirlFriend(阿克曼,18,man,fk you);//3.把对象添加到数组当中arr[0]gf1;arr[1]gf2;arr[2]gf3;arr[3]gf4;//4.求和int sum 0;for (int i 0; i arr.length; i) {GirlFriend gf arr[i];//累加sum gf.getAge();}//5.平均值int avg sum/arr.length;//6.统计年龄比平均值低的有几个打印他们的信息int count 0;for (int i 0; i arr.length; i) {GirlFriend gf arr[i];if(gf.getAge()avg){count;System.out.println(gf.getName(),gf.getAge(),gf.getGender(),gf.getHobby());}}System.out.println(一共count个);}
}
1.3 键盘录入回顾
键盘录入: 第一套体系:
nextInt();接收整数nextDouble();接收小数next();接收字符串遇到空格制表符回车就停止接受。这些符号后面的数据就不会接受了 public static void main(String[] args) {Scanner sc new Scanner(System.in);System.out.println(请输入一个整数);//123 123int num1 sc.nextInt();//123System.out.println(num1);System.out.println(请输入第二个整数);int num2 sc.nextInt();//123System.out.println(num2);}当next中出现空格时可会给下一个键盘的数据接受就不会做键盘录入 2.
public static void main(String[] args) {Scanner sc new Scanner(System.in);System.out.println(请输入一个字符串);String str1 sc.next();System.out.println(str1);System.out.println(请输入第二个字符串);String str2 sc.next();System.out.println(str2);}第二套体系:
nextLine();接收字符串 遇到回车才停止录入
public static void main(String[] args) {Scanner sc new Scanner(System.in);System.out.println(请输入一个字符串);String line1 sc.nextLine();System.out.println(line1);System.out.println(请输入第二个字符串);String line2 sc.nextLine();System.out.println(line2);}但是重要的是键盘录入的两套体系不能混用 弊端
先用nextInt再用nextLine会导致下面的nextLine接受不到数据
public static void main(String[] args) {Scanner sc new Scanner(System.in);System.out.println(请输入一个整数);int num sc.nextInt();//123回车System.out.println(num);//123System.out.println(请输入第一个字符串);String line sc.nextLine();System.out.println(line);//录入不了就结束了}1.4 复杂对象数组练习
1.4.1 复杂练习一 思考要求1和2思路 1.创建一个长度为3的数组2.创建学生对象3.把学生对象添加到数组当中4.再次创建一个学生对象5.唯一性判断5.1已存在---提示重复5.2不存在---添加学生对象6.添加学生对象6.1老数组已经存满6.2老数组没有存满
Student的javabeen包
package test8;public class Student {private int id;private String name;private int age;public Student() {}public Student(int id, String name, int age) {this.id id;this.name name;this.age age;}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 int getAge() {return age;}public void setAge(int age) {this.age age;}
}Test实现要求1和2
package test8;public class Test {public static void main(String[] args) {//1.创建一个数组用来储存学生对象Student[] arr new Student[3];//2.创建学生对象并添加到数组当中Student stu1 new Student(1,zhangsan,23);Student stu2 new Student(2,lisi,24);//3.把学生对象添加到数组当中arr[0]stu1;arr[1]stu2;//要求1再次添加一个学生对象并在添加的时候进行学号的唯一性判断。Student stu4 new Student(4,zhaoliu,26);//唯一性判断//已存在--不用添加//不存在--就可以把学生对象添加进数组boolean flag contains(arr,stu4.getId());if(flag){//已存在--不用添加System.out.println(当前id重复请修改id后再进行添加);}else{//不存在--就可以把学生对象添加进数组//把stu4添加到数组当中//1.数组已经存满---只能创建一个新的数组新数组的长度老数组1//2.数组没有存满--直接添加int count getCount(arr);if(countarr.length){//已经存满//创建一个新的数组,长度老数组的长度1//然后把老数组的元素拷贝到新数组当中Student[] newArr creatNewArr(arr);//把stu4添加进去newArr[count]stu4;//要求2添加完毕之后遍历所有学生信息printArr(arr);}else{//没有存满//[stu1,stu2,null]//getCount获取到的是2表示数组当中已经有了2个元素//还有一层意思如果下一次要添加数据就是添加到2索引的位置arr[count] stu4;//要求2添加完毕之后遍历所有学生信息这样写就与上方重复了//此时就又需要定义方法进行调用printArr(arr);}}}public static void printArr(Student[] arr){for (int i 0; i arr.length; i) {Student stu arr[i];if(stu!null){System.out.println(stu.getId(),stu.getName(),stu.getAge());}}}//创建一个新的数组长度老数组的长度1// 然后把老数组的元素拷贝到新数组当中public static Student[] creatNewArr(Student[] arr) {Student[] newArr new Student[arr.length1];//循环遍历得到老数组中的每一个元素for (int i 0; i arr.length; i) {//把老数组中的元素添加到新数组当中newArr[i]arr[i];}//把新数组返回return newArr;}//定义一个方法判断数组中已经存了几个元素public static int getCount(Student[] arr){//定义一个计数器用来统计int count 0;for (int i 0; i arr.length; i) {if(arr[i]!null){count;}}//当循环结束之后,我就知道了数组中一共有几个元素return count;}//1.我要干嘛 唯一性判断//2.我干这件事需要什么才能完成数组id//3.调用处是否需要继续使用方法的结果public static boolean contains(Student[] arr,int id){//1 2 3 ----3是否存在for (int i 0; i arr.length; i) {//依次获取到数组里面的每一个学生对象Student stu arr[i];//如果没装满stu获取的是null用null调用其他的方法就会报错if(stu!null){//获取数组学生的idint sid stu.getId();//比较if(sid id){return true;}}}//当循环结束之后还没有找到一样的那么就表示数组中要查找的id是不存在的。return false;}
}1.4.2 复杂练习二
Test2实现需求3和4
package test8;public class Test2 {public static void main(String[] args) {//1.创建一个数组用来储存学生对象Student[] arr new Student[3];//2.创建学生对象并添加到数组当中Student stu1 new Student(1,zhangsan,23);Student stu2 new Student(2,lisi,24);Student stu3 new Student(3,wangwu,25);//3.把学生对象添加到数组当中arr[0]stu1;arr[1]stu2;arr[2]stu3;//要求3:通过id删除学生信息//如果存在则删除,如果不存在则提示删除失败。//要找到id在数组中对应的索引int index getIndex(arr,2);if(index0){//如果存在则删除arr[index]null;//遍历数组printArr(arr);}else{//如果不存在则提示删除失败System.out.println(当前id不存在删除失败);}}//1.我要干嘛 找到id在数组中的索引//2.我干这件事需要什么才能完成数组id//3.调用处是否需要继续使用方法的结果 要public static int getIndex(Student[] arr,int id){for (int i 0; i arr.length; i) {//依次得到每一个学生对象Student stu arr[i];//对stu进行一个非空判断if(stu !null){int sid stu.getId();if(sidid){return i;}}}//当循环结束之后还没有找到就表示不存在return -1;}public static void printArr(Student[] arr){for (int i 0; i arr.length; i) {Student stu arr[i];if(stu!null){System.out.println(stu.getId(),stu.getName(),stu.getAge());}}}
}Test3实现要求5
package test8;public class Test3 {public static void main(String[] args) {//1.创建一个数组用来储存学生对象Student[] arr new Student[3];//2.创建学生对象并添加到数组当中Student stu1 new Student(1,zhangsan,23);Student stu2 new Student(2,lisi,24);Student stu3 new Student(3,wangwu,25);//3.把学生对象添加到数组当中arr[0]stu1;arr[1]stu2;arr[2]stu3;//4.先要找到id为2的学生对于的索引int index getIndex(arr,2);//5.判断索引if(index0){//存在则将他的年龄1岁Student stu arr[index];//把原来的年龄拿出来int newAge stu.getAge()1;//把1之后的年龄塞回去stu.setAge(newAge);//遍历数组printArr(arr);}else{//不存在则直接提示System.out.println(当前id不存在修改失败);}}//1.我要干嘛 找到id在数组中的索引//2.我干这件事需要什么才能完成数组id//3.调用处是否需要继续使用方法的结果 要public static int getIndex(Student[] arr,int id){for (int i 0; i arr.length; i) {//依次得到每一个学生对象Student stu arr[i];//对stu进行一个非空判断if(stu !null){int sid stu.getId();if(sidid){return i;}}}//当循环结束之后还没有找到就表示不存在return -1;}public static void printArr(Student[] arr){for (int i 0; i arr.length; i) {Student stu arr[i];if(stu!null){System.out.println(stu.getId(),stu.getName(),stu.getAge());}}}}2. API:应用程序编程接口 例子 其他的API都是存储在JDK-API帮助文档.CHM
2.1 使用帮助文档 API使用步骤
java.lang包非常重要使用java.lang包时不需要import进行导入 API帮助文档网站
可以寻找关键字 API文档练习
public static void main(String[] args) {//1.创建对象Scanner sc new Scanner(System.in);System.out.println(请输入一个小数);//2.接受一个小数double result sc.nextDouble();//3.输出打印System.out.println(result);}3. 字符串String
常见情况 字符串概述 注意 总结
3.1 创建String对象的两种方式
其有两种 直接赋值和用new去构造一个方法 public static void main(String[] args) {//直接赋值String a1111;//空参构造String bnew String();System.out.println(1b2);//传递字符串了解String cnew String(abc);//传递字符数组//应用环境修改字符串 例如把abc 改成qbc//abc--{a,b,c}--{q,b,c}--qbcchar[] d{w,s,s,b};String enew String(d);System.out.println(e);//传递字节数组//应用场景在网络中传输的都是字节信息把字节信息转换成字符串byte[] f{97,98,99,100};//这里不是把数字传递过去而是把数字转成ASCLL表里的字符。String gnew String(f);System.out.println(g);}字符串在内存中的存储方式 字符串常量池 只有直接赋值的字符串才会在这个空间中 在堆内存中 当串池中已经存在一个abc字符串时再次给字符串变量赋值相同的值时会直接复用之前相同字符串的地址。 每new一次就会在堆空间创建一个新的空间可能会造成内存的浪费 所以还是推荐使用直接赋值创建字符串。
3.2 字符串的比较 号比较的原理 字符串常见比较错误 对于不同方式字符串的内容比较 例如 1.
public static void main(String[] args) {//1.创建两个字符串对象String s1 new String(abc);String s2 Abc;//2.号比较//基本数据类型比的是数据值//应用数据类型比的是地址值System.out.println(s1s2);//false//3.比较字符串对象中的内容是否相等boolean result s1.equals(s2);System.out.println(result);//4.比较字符串对象中的内容是否相等忽略大小写boolean result2 s1.equalsIgnoreCase(s2);System.out.println(result2);// true}public static void main(String[] args) {//1.假设我现在键盘录入一个abcScanner sc new Scanner(System.in);System.out.println(请输入一个字符串);String str1 sc.next();//abc 是new出来的//2.代码中再定义一个字符串abcString str2 abc;//3.用比较这两者能一样吗System.out.println(str1 str2);//false为什么直接赋值的和new出来的不一样//结论//以后只要想比较字符串的内容,就必须要用string里面的方法}3.3 字符串练习
3.3.1 练习一用户登录 public static void main(String[] args) {// 1.定义两个变量记录正确的用户名和密码String rightUsername zhangsan;String rightPassword 123456;Scanner sc new Scanner(System.in);//2.键盘录入用户名和密码for (int i 0; i 3; i) {System.out.println(请输入用户名);String username sc.next();System.out.println(请输入密码);String password sc.next();//3.比较if(username.equals(rightUsername)password.equals((rightPassword))){System.out.println(用户登录成功);break;}else{if(i2){// 最后一次机会也输入错误此时要提示账号被锁定System.out.println(账号username被锁定);}else{System.out.println(用户登录失败用户名或密码有误您还剩下(2-i)次机会);//}}}}3.3.2 练习二 ctrlaltv 自动生成左边赋值
chcharAt()方法返回每一个索引对应的索引值 public static void main(String[] args) {// 1. 键盘录入一个字符串Scanner sc new Scanner(System.in);System.out.println(请输入一个字符串);String str sc.next();//2.进行遍历for (int i 0; i str.length(); i) {//i 依次表示字符串的每一个索引//chcharAt()方法返回每一个索引对应的索引值// ctrlaltv 自动str.charAt(i);生成左边char c str.charAt(i);System.out.println(c);}2. public static void main(String[] args) {// 1. 键盘录入一个字符串Scanner sc new Scanner(System.in);System.out.println(请输入一个字符串);String str sc.next();//2.统计---计数器思想//定义三个计数器int bigCount 0;int smallCount 0;int numberCount 0;for (int i 0; i str.length(); i) {//i 依次表示字符串中的每一个索引char c str.charAt(i);if(cacz){//char类型的变量在参与计算的时候自动类型提升为int查询ascii码表smallCount;}else if(cAcZ){bigCount;}else if(c0c9){numberCount;}}System.out.println(小写字母有smallCount个);System.out.println(大写字母有bigCount个);System.out.println(数字字母有numberCount个);}3.3.3 练习三字符串拼接和反转 public static void main(String[] args) {//1.我要干嘛?---遍历数组并把数组拼接成一个字符串//2.我干这件事情需要什么才能完成?---数组//3.我干完了是否要把结果返回给调用处---返回一个拼接之后的字符串// 如果调用处需要继续使用,那么必须返回//如果调用处不需要继续使用那么可以返回也可以不返回int[] arr{1,2,3};String str arrToString(arr);System.out.println(str);//123}public static String arrToString(int[] arr){if(arrnull){return;}if(arr.length0){return [];}String result [;//当代码执行到这里表示什么//表示数组不是null也不是长度为0的for (int i 0; i arr.length; i) {if(iarr.length-1){result resultarr[i];}else{result resultarr[i],;}}//此时拼接右括号result result ];return result;}2.
public class ArithmeticoperatorDemo1 {public static void main(String[] args) {String result reverser(cnm);System.out.println(result);}public static String reverser(String str){String result ;for (int i str.length()-1; i 0; i--) {char c str.charAt(i);result c;}return result;}
} 3.3.4 练习四
3.3.5 练习五
3.4 StringBuilder
使用StringBuilder的场景
1.字符串的拼接2.字符串的反转
相当于一个字符串的工具StringBuilder不是字符串类型 3.4.1 StringBuilder构造方法 3.4.2 StringBuilder常用方法 1.append 添加方法
public static void main(String[] args) {//1.创建对象StringBuilder sb new StringBuilder();//打印//普及://因为stringBuilder是Java已经写好的类// java在底层对他做了一些特殊处理。//打印对象不是地址值而是属性值。System.out.println(sb);}所以它没有返回一个地址值
public static void main(String[] args) {//1.创建对象StringBuilder sb new StringBuilder(abc);//2.添加元素sb.append(1);sb.append(2.3);sb.append(true);System.out.println(sb);}2.reverse 反转方法
sb.reverse();3.length 获取长度方法 int len sb.length();System.out.println(len);4.toString
public static void main(String[] args) {//1.创建对象StringBuilder sb new StringBuilder(abc);//2.添加字符串sb.append(aaa);sb.append(wwww);sb.append(xxxx);System.out.println(sb);//abcaaawwwwxxxx只是在一个容器里面//3.再把StringBuilder变回字符串类型String str sb.toString();System.out.println(str);//现在的abcaaawwwwxxxx才是字符串类型}3.4.3 链式编程
当我们在调用一个方法的时候不需要用变量接收他的结果可以继续调用其他方法 1.
public static void main(String[] args) {String len getString().substring(1).replace(b,w);System.out.println(len);int len2 len.length();System.out.println(len2);}public static String getString(){Scanner sc new Scanner(System.in);System.out.println(请输入一个字符串);String str sc.next();return str;}2. 将上方3.4.2内容的第4点 sb.append(aaa);sb.append(wwww);sb.append(xxxx);可写成-一条链子效果相同
sb.append(aaa).append(wwww).append(xxxx);练习 1. equals() 方法用于比较两个字符串的内容是否相等。
package com.itheima.demo1;import java.util.Scanner;public class ArithmeticoperatorDemo1 {public static void main(String[] args) {// 1.键盘录入字符串Scanner sc new Scanner(System.in);System.out.println(请输入一个字符串);String str sc.next();//2.反转键盘录入的字符串String result new StringBuilder().append(str).reverse().toString();//.3比较if(str.equals(result)){System.out.println(当前字符串是对称字符串);}else{System.out.println(当前字符串不是对称字符串);}}
}2.
package com.itheima.demo1;public class ArithmeticoperatorDemo1 {public static void main(String[] args) {//1.定义数组int[] arr {1, 2, 3, 4};//2.定义一个接受字符数组的子函数把arr放进去String str arrString(arr);System.out.println(str);}public static String arrString(int[] arr) {//3. new一个StringBuilder容器用来存放字符串StringBuilder sb new StringBuilder();sb.append([);//将 [ 先加入到容器中//4.循环遍历分割数组for (int i 0; i arr.length; i) {//5.采用判断语句如果加入到了最后一个字时就ilength-1,才会不打印 , 逗号//其他加入的时候就带 逗号一加入进容器if (i arr.length - 1) {sb.append(arr[i]);} else {sb.append(arr[i]).append(,);}}//循环结束之后填右边括号sb.append(]);//6.完成后返回sb的字符串类型return sb.toString();}
}3.4.4 StringJoiner
对于有时候StringBuilder按照数组拼接字符串的时候就比较麻烦了中间有的时候拼有的时候不拼 StringJoiner概述 StringJoiner对象的创建
StringJoiner的成员方法
1.add() 添加内容
delimiter中间间隔的符号prefix开始的符合suffix结尾的符号
public static void main(String[] args) {StringJoiner sj new StringJoiner(-----);//2.添加元素sj.add(aaa).add(bbbb).add(ccc);//3.打印结果System.out.println(sj);}2.
public static void main(String[] args) {StringJoiner sj new StringJoiner(,,[,]);//2.添加元素sj.add(aaa).add(bbbb).add(ccc);int len sj.length();System.out.println(len);//14//3.打印结果System.out.println(sj);//容器的类型String str sj.toString();System.out.println(str);//字符串的类型}总结
3.4.5 字符串原理
扩展底层原理1和2字符串原理 扩展底层原理3字符串拼接的底层原理 1.当等号的右边没有变量时 在编译的时候就会将a “b” “c拼接为abc”
2.当等号的右边有变量时 在jdk8以前系统底层会自动创建一个StringBuilder对象然后再调用其append方法完成拼接。 拼接后再调用其toString方法转换为String类型而toString方法的底层是直接new了一个字符串对象。 在jdk8之后在编译时会先预估字符串的长度并创建一个数组再把数组变成一个字符串这样就消耗性能了。 面试练习题 2. 那就采用StringBuilder 和StringJoiner 进行优化
扩展底层原理5StringBuilder提高效率原理
stringBuilder是一个内容可变的容器所有要拼接的内容都会往StringBuilder中放不会创建很多无用的空间节约内存 3、4原理小结
扩展底层原理5:StringBuilder源码分析 总结
ctrl n IDEA快捷键 出现搜索界面
在所有位置里寻找搜索界面默认在当前项目文件里找不到
--------- ctrl f12 ----寻找toString
3.4.6 字符串综合练习 2. 3.
4. 集合 集合是一个容器可以用来存储数据和数组不同的是集合的长度可以发生变化。当添加元素时会自动扩容。 集合可以存储引用数据类型不能直接存储基本数据类型要把基本数据类型变成其对应的包装类才能存储。 4.1 ArrayList 集合之一
ArrayList集合的创建 public static void main(String[] args) {//1.创建集合的对象//泛型:指限定集合中存储数据的类型就是 里面的//ArrayListString list new ArrayListString();// jDK7之后:ArrayListString list new ArrayList();System.out.println(list);//此时我们创建的是ArrayList的对象//这个类在底层做了一些处理//打印对象不是地址值,而是集合中存储数据内容 也就是[]//在展示的时候会拿[]把所有的数据进行包裹}ArrayList成员方法
add()和remove的返回值都是布尔值add默认返回true不用管而remove在删除成功时返回true失败时返回false 同时remove还可以根据索引进行删除返回值是被删除的元素set是修改指定索引上的值返回被覆盖的值。get就是获取相应索引的元素size就是集合的长度类似于length
public static void main(String[] args) {//1.创建集合的对象ArrayListString list new ArrayList();//2.添加元素list.add(aaa);list.add(aaa);list.add(www);list.add(ddd);System.out.println(2list);//3.删除元素boolean result1 list.remove(aaa);System.out.println(3result1);//当要删除的元素不存在时就会falseSystem.out.println(3list);//把被删除的元素进行返回String str list.remove(2);System.out.println(3str);System.out.println(3list);//4.修改元素String res list.set(1, cccc);//把替换的元素进行返回System.out.println(4res);System.out.println(4list);//5.查询元素String s list.get(0);System.out.println(5s);System.out.println(5list);//6.遍历元素 list.forifor (int i 0; i list.size(); i) {//list.get(i) 元素String s1 list.get(i);System.out.println(6s1);System.out.println(6list);}}4.2 集合综合练习
4.2.1 添加字符串和整数遍历 public static void main(String[] args) {ArrayListString list new ArrayList();list.add(aaa);list.add(bbb);list.add(ccc);list.add(ddd);//遍历System.out.print([);for (int i 0; i list.size(); i) {if(ilist.size()-1){System.out.print(list.get(i));}else{System.out.print(list.get(i),);}}System.out.println(]);}2. 下方遍历代码一样中间改变
ArrayListInteger list new ArrayList();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);添加字符类型遍历也是同理 ArrayListCharacter list new ArrayList();list.add(a);list.add(b);list.add(c);list.add(d);4.2.2 基本数据类型的包装类
这里的包装类实际上就是泛型里的关键字 jdk5以后int Intleger 之间是可以互相转化的
4.2.3 添加学生对象并遍历 public static void main(String[] args) {ArrayListStudent list new ArrayList();//2.创建学生对象Student s1 new Student(zhangsan,23);Student s2 new Student(magua,24);Student s3 new Student(xiaolaoban,25);//3.添加元素list.add(s1);list.add(s2);list.add(s3);//4.遍历集合for (int i 0; i list.size(); i) {Student stu list.get(i);System.out.println(stu.getName(),stu.getAge());}}2. 遍历思路
public static void main(String[] args) {ArrayListStudent list new ArrayList();// 长度为0//2.键盘录入学生的信息并添加到集合当中Scanner sc new Scanner(System.in);for (int i 0; i 3; i) {Student s new Student();System.out.println(请输入学生的姓名);String name sc.next();System.out.println(请输入学生的年龄);int age sc.nextInt();//把name和age赋值给学生对象s.setName(name);s.setAge(age);//把学生对象添加到集合当中list.add(s);}//集合里面是否有学生对象//有 没有System.out.println(list.size());//3for (int i 0; i list.size(); i) {Student stu list.get(i);System.out.println(stu.getName(),stu.getAge());}}4.2.4 添加用户对象并判断是否存在 javabean部分
package test10;public class User {private String id;private String username;private String password;public User() {}public User(String id, String username, String password) {this.id id;this.username username;this.password password;}public String getId() {return id;}public void setId(String id) {this.id id;}public String getUsername() {return username;}public void setUsername(String username) {this.username username;}public String getPassword() {return password;}public void setPassword(String password) {this.password password;}
}
Test部分
package test10;import java.util.ArrayList;public class test {public static void main(String[] args) {//1.创建集合ArrayListUser list new ArrayList();//2.创建三个用户对象User u1 new User(magua001,zhangsan,12345);User u2 new User(magua002,lisi,12345678);User u3 new User(magua003,wangwu,12345asd);//3.把用户对象添加到集合当中list.add(u1);list.add(u2);list.add(u3);//4.调用方法查看id是否存在boolean flag contains(list, magua001);System.out.println(flag);}public static boolean contains(ArrayListUser list,String id){
// for (int i 0; i list.size(); i) {
// User u list.get(i);
// String uid u.getId();
// if(uid.equals(id)){
// //如果找到了直接返回true
// return true;
// }
// }
// //当循环结束表示集合里面所有的元素都比较完毕还没有一样的
// //那么就返回false
// return false;return getIndex(list,id)0;}public static int getIndex(ArrayListUserlist,String id){for (int i 0; i list.size(); i) {User u list.get(i);String uid u.getId();if(uid.equals(id)){return i;}}return -1;}
}4.2.5 添加手机对象并返回要求的数据 phone的javabean
package test11;public class Phone {private String brand;private int price;public Phone() {}public Phone(String brand, int price) {this.brand brand;this.price price;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand brand;}public int getPrice() {return price;}public void setPrice(int price) {this.price price;}
}test部分
public static void main(String[] args) {//1.创建集合ArrayListPhone list new ArrayList();//2.创建三个用户对象Phone p1 new Phone(xiaomi,1000);Phone p2 new Phone(iphone,4000);Phone p3 new Phone(cuizi,2000);//3.把用户对象添加到集合当中list.add(p1);list.add(p2);list.add(p3);//4.调用方法ArrayListPhone phoneInfoList getPhoneInfo(list);//5.遍历集合for (int i 0; i phoneInfoList.size(); i) {Phone phone phoneInfoList.get(i);System.out.println(phone.getBrand(),phone.getPrice());}}//1.我要干嘛?查询手机信息//2.我干这件事情,需要什么才能完成?集合//3.我干完了方法的调用处是否需要继续使用结果?返回//技巧://如果我们要返回多个数据可以把这些数据先放到一个容器当中再把容器返回/集合数组public static ArrayListPhone getPhoneInfo(ArrayListPhone list){//定义一个集合用于存储价格低于3000的手机对象ArrayListPhone resultList new ArrayList();//遍历集合for (int i 0; i list.size(); i) {Phone p list.get(i);int price p.getPrice();//如果当前手机的价格低于3000if(price3000){resultList.add(p);}}return resultList;//返回的是集合函数的返回值类型就得是集合}5. 学生管理系统
学会阅读需求文档在了解需求文档后自己画出需求的结构流程图业务流程图 流程图 Ctrl alt t 全选中内容后快捷生成结构环绕方式 StudentTest第一部分
package test1;import java.util.ArrayList;
import java.util.Scanner;public class StudentTest {public static void main(String[] args) {ArrayListStudent list new ArrayList();while (true) {//不要把ArrayListStudent list new ArrayList();//放在循环内部这样在添加学生到list后再循环一次list又变成了0这样查询的时候就总是无法查到System.out.println(----------------欢迎来到小黑子的学生管理系统----------------);System.out.println(1添加学生);System.out.println(2删除学生);System.out.println(3修改学生);System.out.println(4查询学生);System.out.println(5退出);System.out.println(请输入您的选择);Scanner sc new Scanner(System.in);//定义一个字符串来接收String choose sc.next();switch (choose) {case 1 - addStudnet(list);case 2 - deleteStudnet(list);case 3 - updateStudnet(list);case 4 - queryStudnet(list);case 5 - {System.out.println(退出);System.exit(0);//停止虚拟机运行}default - System.out.println(没有这个选项);}}}//添加学生public static void addStudnet(ArrayListStudent list) {//利用空参构造先创建学生对象Student s new Student();Scanner sc new Scanner(System.in);String id null;while (true) {System.out.println(请输入学生的id);id sc.next();boolean flag contains(list, id);if (flag) {//true 表示id已经存在需要重新录入System.out.println(id已经存在请重新录入);} else {//表示id不存在唯一s.setId(id);break;}}System.out.println(请输入学生的姓名);String name sc.next();s.setName(name);System.out.println(请输入学生的年龄);int age sc.nextInt();s.setAge(age);System.out.println(请输入学生的家庭住址);String address sc.next();s.setAddress(address);//把学生对象添加到集合当中list.add(s);//提示用户System.out.println(学生信息添加成功);System.out.println(list.size());}//删除学生public static void deleteStudnet(ArrayListStudent list) {Scanner sc new Scanner(System.in);System.out.println(请输入要删除的id);String id sc.next();//查询id在集合中的索引int index getIndex(list, id);//对index进行判断//如果-1就表示索引不存在结束方法返回初始菜单if (index 0) {//如果大于等于0的表示存在直接删除list.remove(index);System.out.println(id为 id 的学生删除成功);} else {System.out.println(id不存在删除失败);}}//修改学生public static void updateStudnet(ArrayListStudent list) {Scanner sc new Scanner(System.in);System.out.println(请输入要修改学生的id);String id sc.next();int index getIndex(list,id);if(index -1){System.out.println(要修改的idid不存在请重新输入);return;}//当代码执行到这里表示什么表示当前id是存在的//获取要修改的学生对象Student stu list.get(index);//输入其他的信息并修改System.out.println(请输入修改的学生姓名);String newName sc.next();stu.setName(newName);System.out.println(情输入修改的学生年龄);String newAge sc.next();stu.setName(newAge);System.out.println(情输入修改的学生家庭住址);String newAddress sc.next();stu.setName(newAddress);System.out.println(学生信息修改完成);}//查询学生public static void queryStudnet(ArrayListStudent list) {System.out.println(list.size());if (list.size() 0) {System.out.println(当前无学生信息请添加后再查询);return;}//打印表头信息System.out.println(id\t\t姓名\t年龄\t家庭住址);//当代码执行到这里时表示集合是有数据的遍历集合的每个数据for (int i 0; i list.size(); i) {Student stu list.get(i);System.out.println(stu.getId() \t stu.getName() \t stu.getAge() \t stu.getAddress());}}//判断id 的方法public static boolean contains(ArrayListStudent list, String id) {
// //循环遍历每一个学生对象
// for (int i 0; i list.size(); i) {
// //拿到学生对象后获取id并进行判断
// Student stu list.get(i);
// String sid stu.getId();
// if(sid.equals(id)){
// //存在,true
// return true;
// }
// }
// //不存在方法就返回false
// return false;return getIndex(list, id) 0;}//通过id获取索引的方法public static int getIndex(ArrayListStudent list, String id) {//遍历集合for (int i 0; i list.size(); i) {//得到每一个学生对象Student stu list.get(i);//得到每一个学生对象的idString sid stu.getId();//拿着集合中的学生id跟要查询的id进行比较if (sid.equals(id)) {//如果一样那么就返回索引return i;}}return -1;}
} swich语句不能用箭头表达式java版本换成jdk17以上行了。
5.1 学生管理系统升级版
需求图 流程图
1.注册 2.登录 3.忘记密码 6. 面向对象进阶
6.1 static
6.1.1 static-静态变量 static静态变量静态变量被该类所有对象共享,是Java中的一个修饰符可以修饰成员方法成员变量 javabean类
public class Student {private String name;private int age;private String gender;public static String teacherName;public Student() {}public Student(String name, int age, String 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 String getGender() {return gender;}public void setGender(String gender) {this.gender gender;}//行为public void study(){System.out.println(name正在学习);}public void show(){System.out.println(name,age,genderteacherName);}测试类 public static void main(String[] args) {//1.创建学生对象Student s1 new Student();s1.setName(张三);s1.setAge(23);s1.setGender(man);s1.teacherName 麻瓜;s1.study();s1.show();//2.创建第二个学生对象Student s2 new Student();s2.setName(李四);s2.setAge(25);s2.setGender(man);s2.study();s2.show();}当这里的teacherName被赋值后static会被Student类里所有对象共享公共的一个属性
静态变量是随着类的加载而加载的优先于对象出现被赋值是单独存储再堆内存中的静态区域
示意图 静态区里的变量是对象共享的在内存中只有一份谁用谁拿非静态的变量是每一个对象所独有的每一个对象里的非静态的变量都是单独存放的。
判断一个变量是否是静态变量主要就是两个字共享 需要共享的变量就是静态变量
6.1.2 static-静态方法和工具
静态方法 工具类 工具类帮助我们做一些事情的,但是不描述任何事物的类 目前一共学习了三种类 工具类的要求
这里的第2个私有化构造方法就是
public class Student {private public Student() {}
}一个类一旦被私有化构造方法后就不能创建这个类的对象了。
练习 1. javabean类
public class ArrayUtil {//私有化构造方法//目的:为了不让外界创建他的对象private ArrayUtil(){}public static String printArr(int[] arr){//一到字符串的拼接就一定要想到StringBuildeStringBuilder sb new StringBuilder();sb.append([);for (int i 0; i arr.length; i) {if(iarr.length-1){sb.append(arr[i]);}else{sb.append(arr[i]).append(, );}}sb.append(]);return sb.toString();}public static double getAverage(double[] arr){double sum 0;for (int i 0; i arr.length; i) {sum sum arr[i];}return sum/arr.length;}
}测试类
public class TestDemo {public static void main(String[] args) {//测试工具类的两个方法是否正确int[] arr1 {1, 2, 3, 4, 5};String str ArrayUtil.printArr(arr1);System.out.println(str);double[] arr2 {1.5,23.43,654.43,1.23,23.3};double avg ArrayUtil.getAverage(arr2);System.out.println(avg);}
}2. 工具类
import java.util.ArrayList;public class StudentUtil {private StudentUtil(){}//静态方法public static int getMaxAgeStudent(ArrayListStudent list){//1.定义一个参照物int max list.get(0).getAge();//2.循环遍历集合for (int i 0; i list.size(); i) {//i 索引 list.get(i)元素/学生对象 我们还需要getAge获取到年龄之后再进行比较int tempAge list.get(i).getAge();if(tempAgemax){max tempAge;}}//3.直接返回return max;}
}Test部分调用工具类方法 //4.调用工具类方法int maxAgeStudent StudentUtil.getMaxAgeStudent(list);System.out.println(maxAgeStudent);6.1.3 static-注意事项 在非静态方法中有一个隐藏的this这个this就表示当前方法调用者的地址值 在第一次调用show()方法时虚拟机就会把第一次调用者的地址赋值给方法中的this就像图中所示 第二次同理虚拟机会把第二次调用者的地址赋值给方法中的this this的值 this的这一特性就是区分不同对象的 即在调用成员变量时变量前面有隐含的this从而显示出不同变量的结果 上面sout里的this可以省略
而在static静态方法中是没有这个this关键字的原因就是静态方法是公用的而this一般是独立的对象进行使用不符合公用的理念。
示意图
静态方法不能访问非静态成员变量也就是实例变量即对象 因为在使用静态方法时通过类名调用会直接到静态存储位置去找变量而非静态的变量是随着对象的创建而创建的在静态存储位置找不到所以静态方法不能调用非静态成员变量
静态方法不能访问非静态的成员方法 因为非静态的方法需要调用者而在静态方法中是没有this的也就没有调用者自然就不能使用了
综上静态方法只能调用静态的内容
非静态方法可以访问所有 因为静态的是公用的所以非静态既可以访问到静态也可以访问非静态
小结
6.1.4 重新认识main方法
JVM虚拟机 例子
点击IDEA右上角的锤子旁边的按钮 在程序参数里填写args即可返回值
6.2 继承
6.2.1 封装
封装 对象代表什么就得封装对应的数据并提供数据对应的行为 像这种相同的行为太多了这时候就需要用到封装 封装完行为方法之后就要用到继承了
6.2.2 继承的描述
继承实际上就是类跟类之间的父子关系 什么时候用继承 小结 继承需要学习的点
6.2.3 继承的特点 即儿子继承父亲父亲继承爷爷 即子类的父类是直接父类父类的父类是子类的间接父类
java中有一个祖宗类就是Object每一个类都直接或间接继承于Object 小结
练习 设计继承体系时尽量先搞清楚体系逻辑画一张图从子类到父类 设计的核心就是共性的内容抽取子类是父类的一种 书写代码时从父类到子类 小结
6.2.4 子类继承父类的特性 构造方法不论私有private还是非私有像public等的构造方法子类都是不能继承的 例子 成员变量不论私有private不能直接调用还是非私有像public等的成员变量子类都是可以继承的相当于从父类哪里copy了一份过来
1.没有用private修饰的继承成员变量的内存图 2.有用private修饰的继承成员变量的内存图
这里new出来一个子类后会把堆内存中开辟出来的空间分为两部分第一部分是继承父类的成员变量第二类是子类自己的成员变量如果父类的成员变量使用private修饰后子类对象在堆内存中就无法使用继承父类的成员变量。 父类会把非private非static和非final的方法这些方法统称为虚方法抽取出来放到虚方法表里在继承的时候父类会把虚方法表交给子类复制子类可以添加新的虚方法加入到子类的虚方法表中使后代继续复制 成员方法非私有的成员方法虚方法可以被继承私有的成员方法就不能被继承下来
运行效率低下 以下如此可以大大提高性能 例子
6.2.5 终端的jps和jhsdb hsdb
在终端中输入jps得到类中获得的id 输入jhsdb hsdb 打开HotSpot Debugger
HSDBHotspot Debugger) 是一款内置于 SA 中的 GUI 调试工具可用于调试 JVM运行时数据从而进行故障排除。 在file中寻找到第一个点击进入 从jps中获得的id输入ok 之后显示
在tools里找到Memory Viewer 在tools里找到Inspector
6.2.6 继承中成员变量和成员方法的访问特点
继承成员变量
继承的成员变量的访问特点 就近原则谁离我近我就用谁 即优先级为 方法内的成员变量子类的成员变量父类的成员变量 在使用一个成员变量时会先在局部的方法内找如果方法内没有就会到本类子类中去找本类中再没有就会到父类中去找 在上述代码中name就是“ziShow”如果“ziShow”没有name就是“Zi”如果“Zi”再没有那么name就是“Fu” 当然也可以同时访问这三个成员变量
例子 1.
public class Test {public static void main(String[] args) {Zi zinew Zi();zi.ziShow();}
}
class Fu{String nameFu;
}
class Zi extends Fu{String nameZi;public void ziShow(){String nameziShow;System.out.println(name);System.out.println(this.name);System.out.println(super.name);}
}2. 即使用this关键字可以访问本类的成员变量使用super关键字可以访问父类的成员变量。 语法
this.变量名super.变量名
注在子类中最多使用一个super
小结
继承成员方法
继承的成员方法的访问特点
直接调用满足就近原则谁近调用谁super调用直接访问父类
与上面成员变量的特点一样都是就近原则都是thissuper
public class Test {public static void main(String[] args) {Zi zinew Zi();zi.show();}
}
class Fu{String nameFu;public void eat(){System.out.println(chifan父类被调用);}
}
class Zi extends Fu{String nameZi;//这里进行了方法的重写由于父类的方法不能满足子类的需求从而进行了方法的重写Overridepublic void eat(){System.out.println(heshui子类被调用);}public void show(){eat();this.eat();super.eat();}
}方法重写的本质 新的方法覆盖旧的方法(虚方法表) 方法重写注意事项和要求 私有方法不能进行重写重写方法时也可以调用父类的方法
练习 总结
6.2.6 继承中的构造方法
特点 1.父类中的构造方法不会被子类继承 2.子类中所有的构造方法默认先访问父类中的无参构造再执行自己 第二条出现的原因 例子 所以子类的构造方法的第一句都会是super()即使不写也会存在于第一行。 这里的super()就是调用父类的空参构造方法 如果想调用父类的有参构造就必须手动写super进行调用 小结
6.2.7 this、super关键字总结
this 就相当于一个局部变量表示当前方法调用者的地址值 super 就代表父类的存储空间
this与super的区别
关键字访问成员变量访问成员方法访问构造方法thisthis.成员变量 访问本类成员变量this.成员方法访问本类成员方法this(…)访问本类构造方法supersuper.成员变量 访问父类成员变量super. 访问父类成员方法super(…)访问父类构造方法
当使用this方法来访问本类构造方法
public class Person {String name;int age;String gender;public Person() {this(null,0,男);}public Person(String name,int age,String gender){this.namename;this.ageage;this.gendergender;}
}这里空参构造里的this(null,0,男);就是使用this来访问构造方法并赋予初始值 且使用this()后虚拟机就不会自动添加super()了 练习
Employeer:
public class Employee {//1.类名见名知意//2.所有的成员变量都需要私有//3.构造方法空参带全部参数的构造)//4.get/ setprivate String id;private String name;private double salary;public Employee(){}public Employee(String id, String name, double salary) {this.id id;this.name name;this.salary salary;}public String getId() {return id;}public void setId(String id) {this.id id;}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 void work(){System.out.println(员工在工作);}//吃饭public void eat(){System.out.println(吃米饭);}
}Manager:
public class Manager extends Employee{private double bouns;//空参构造public Manager(double bouns) {this.bouns bouns;}//带全部参数的构造//父类子类public Manager(String id, String name, double salary, double bouns) {super(id, name, salary);this.bouns bouns;}public double getBouns() {return bouns;}public void setBouns(double bouns) {this.bouns bouns;}Overridepublic void work() {System.out.println(管理其他人);}
}Cook:
public class Cook extends Employee{public Cook(){}public Cook(String id, String name, double salary) {super(id, name, salary);}Overridepublic void work() {System.out.println(厨师正在炒菜);}
}Test:
public class Test {public static void main(String[] args) {//创建对象并赋值调用Manager m new Manager(magua001,小笼包,15000,8000);System.out.println(m.getId(),m.getName(),m.getSalary(),m.getBouns());m.work();m.eat();Cook c new Cook();c.setId(magua002);c.setName(lisi);c.setSalary(8000);System.out.println(c.getId(),c.getName(),c.getSalary());c.work();c.eat();}
}6.3 认识多态 多态的概念: 封装是多态的必要条件继承是多态的前提条件 多态的应用场景 不同的用户对象采用同样的代码模块会出现冗余 解决方案 多态的含义 多种形态同种类型的对象表现出的不同形态 可以以父类来创建子类对象即使用父类型作为参数可以接收所有子类对象 多态语法 父类类型 对象名称子类对象 多态可以根据调用对象的不同使用对应的方法 例如 Person mannew Student()这里Person是父类Student是子类 但是多态的使用要满足以下前提 例子
Person类:
public class Person {private String name;private int age;public Person() {}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 void show(){System.out.println(name,age);}
}Student类:
public class Person {private String name;private int age;public Person() {}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 void show(){System.out.println(name,age);}
}Teacher类:
public class Teacher extends Person{Overridepublic void show() {System.out.println(老师的信息为getName(),getAge());}
}Adminnistrator类
public class Administrator extends Person{Overridepublic void show() {System.out.println(管理员的信息为getName(),getAge());}
}测试类
public class Test {public static void main(String[] args) {//创建三个对象并调用register方法Student s new Student();s.setName(张三);s.setAge(18);Teacher t new Teacher();t.setName(麻瓜);t.setAge(30);Administrator admin new Administrator();admin.setName(管理员);admin.setAge(35);//不管传递什么对象都可以被下方Person接收//这就是多态的原因register(s);register(t);register(admin);}//这个方法既能接收老师,又能接收学生,还能接收管理员// 只能把参数写成这三个类型的父类public static void register(Person p){p.show();}
}总结
6.3.1 多态中调用成员的特点
父类 对象名new 子类() 遵循两个口诀: 编译看左边的解释 javac编译代码时会看左边的父类有没有这个变量或方法如果有编译成功如果没有编译失败即必须要有父类的方法 运行也看左边的解释 javac运行代码的时候实际获取的就是左边父类中成员变量的值。 即对象调用遵循以上两个规则。 同理方法调用也是如此只不过在运行时会运行子类的方法即 右边
内存图解 例子
//父类Person
package com.inherit.study;public class Person {String name人;int age;String gender;public Person() {}public Person(String name,int age,String gender){this.namename;this.ageage;this.gendergender;}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 getGender() {return gender;}public void setGender(String gender) {this.gender gender;}public void show(){System.out.println(name age);}
}
//子类Student
package com.inherit.study;public class Student extends Person {String name学生;Overridepublic void show(){System.out.println(学生的信息为getName() getAge());}
}
//测试类
package com.inherit.study;public class test3 {public static void main(String[] args) {Person prnew Student();System.out.println(pr.name);pr.show();}}可以看到父类的成员变量显示出来子类的成员变量没有显示并且子类的方法被运行父类的方法没有运行
子类的方法能运行的原因是子类重写的方法是虚方法在虚方法表里覆盖了父类的虚方法。 如果是子类 对象名子类()这种形式调用成员变量时会先在子类的内存空间寻找成员变量子类的内存空间没有时才会到父类的内存空间去找这是继承的特性而在多态中父类 对象名new 子类()如果父类里没有相应的成员变量会直接报错。
6.3.2 多态的优势和弊端
优势 即只需把后面标红的代码修改就可以了
弊端
不能调用子类的特有功能因为子类的特有方法不是重写的是子类独有的父类里没有所以不能调用会报错。
解决方案 用强制类型转换把父类型转换为子类型不能随便转换要对应着转换 例子
public class Test {public static void main(String[] args) {//创建对象Animal a new Dog();a.eat();//多态的弊端//不能调用子类的特有功能很错的原因?//当调用成员方法的时候编译看左边运行看右边//那么在编译的时候会先检查左边的父类中有没有这个方法如果没有直接报错。//a.lookHome();Animal没有lookHome() 报错//解决方案//变回子类就可以了//Dog d (Dog) a;//d.lookHome();//细节:转换的时候不能瞎转如果转成其他类的类型就会报错//Cat c (Cat) a;//c.CatchMouse(); 已经new成狗了就不能再变成猫}
}class Animal{public void eat(){System.out.println(动物在吃东西);}
}class Dog extends Animal{Overridepublic void eat() {System.out.println(狗吃骨头);}public void lookHome(){System.out.println(狗看家);}
}class Cat extends Animal{Overridepublic void eat() {System.out.println(猫吃小鱼干);}public void CatchMouse(){System.out.println(猫抓老鼠);}
}6.3.3 instanceof 判断是不是相应类型
可以用instanceof关键字来判断是不是相应类型 对象名 instanceof 类 如果是相应类型会返回true否则返回false
//可以利用判断语句进行判断类型是否转换if(a instanceof Dog){Dog d (Dog) a;d.lookHome();} else if(a instanceof Cat){Cat c (Cat) a;c.CatchMouse();}else{System.out.println(没有这个类型无法转换);}java14的新特性 对象名 instanceof 类 变量名 如果是相应类型会直接变成相应类型的变量否则结果是false
if(a instanceof Dog d){d.lookHome();} else if(a instanceof Cat c){c.CatchMouse();}else{System.out.println(没有这个类型无法转换);}小结
6.3.4 多态综合练习 Animal类
public class Animal {private int age;private String color;public Animal() {}public Animal(int age, String color) {this.age age;this.color color;}public void eat(String something){System.out.println(动物在吃something);}public int getAge() {return age;}public void setAge(int age) {this.age age;}public String getColor() {return color;}public void setColor(String color) {this.color color;}
}Dog类
public class Dog extends Animal{public Dog(){}public Dog(int age,String color){super(age,color);}//行为//eat(String something ) (something表示吃的东西//看家lookHome方法(无参数)Overridepublic void eat(String something) {System.out.println(getAge()岁的getColor()黑颜色的狗两只前腿死死的抱住something骨头猛吃);}public void lookHome(){System.out.println(狗在看家);}
}Cat类
public class Cat extends Animal{public Cat() {}public Cat(int age, String color) {super(age, color);}Overridepublic void eat(String something) {System.out.println(getAge()岁的getColor()黑颜色的狗两只前腿死死的抱住something骨头猛吃);}public void catchMouse(){System.out.println(猫抓老鼠);}
}Person类
public class Person {private String name;private int age;public Person() {}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 void keePet(Dog dog,String something){
// System.out.println(年龄为age岁的name养了一只dog.getColor()颜色的dog.getAge()岁的狗);
// dog.eat(something);
// }
// //饲养猫
// public void keePet(Cat cat,String something){
// System.out.println(年龄为age岁的name养了一只cat.getColor()颜色的cat.getAge()岁的猫);
// cat.eat(something);
// }//想要一个方法能接收所有的动物包括猫包括狗//方法的形参可以写这些类的父类 Animalpublic void keepPet(Animal a,String something){if(a instanceof Dog d){System.out.println(年龄为age岁的name养了一只a.getColor()颜色的a.getAge()岁的狗);d.eat(something);}else if(a instanceof Cat c){System.out.println(年龄为age岁的name养了一只c.getColor()颜色的c.getAge()岁的猫);c.eat(something);}else{System.out.println(没有这种动物);}}}测试类
public class Test {public static void main(String[] args) {//创建对象并调用方法
// Person p new Person(老王,30);
// Dog d new Dog(2,墨);
// p.keePet(d,骨头);
//
// Person p2 new Person(老李,25);
// Cat c new Cat(4,灰);
// p2.keePet(c,鱼);Person p new Person(老王,30);Dog d new Dog(2,黑);Cat c new Cat(3,灰);p.keepPet(d,骨头);p.keepPet(c,鱼);}
}6.4 包和 final
6.4.1 包
包的起名规则 公司域名反写包的作用 包名加上类名才是全部的类名下面的名字太长了 改进如果想在一个包里使用其他包的类名就需要引用使用的那个包的名字加上类名 import 包名.类名 这样就可以使用其他包的类了 注意事项 使用两个包的同名类时不需要导包了直接使用同名类 小结
6.4.2 final 与static类似的关键字
在代码中一旦被final修饰就表示被修饰的内容不能改变了有点像JavaScript的const。 final可以修饰方法类和变量
修饰方法时 表示该方法是最终方法不能被重写修饰类时 表示该类是最终类不能被继承修饰变量时 这个变量就会变为一个常量只能被赋值一次 使用final的场景 如果定义的方法是一种规则时可以用final 主要还是用final来修饰变量 常量 主要是第二点对象的内部可以改变。
字符串不可变的原因就是final和private ieda快捷键 crtlshiftu可以让字母变成大写 小结
6.5 权限修饰符和代码块
6.5.1 权限修饰符 权限修饰符的分类 有四种类被访问的范围从小到大分为private空着不写默认情况protectedpublic
修饰符同一个类中的作用范围同一个包里的其他类的作用范围不同包下的子类的作用范围不同包下的无关类的作用范围private可以不行不行不行空着不写默认可以可以不行不行protected可以可以可以不行public可以可以可以可以实际开发中一般来讲只会用private和public且遵守以下规则: 6.5.2 代码块 代码块可以分为三类 局部代码块构造代码块静态代码块 局部代码块
作用提前结束变量的生命周期例如上面的a代码块结束后a就会消失 这个技术现在已经用不到了
构造代码块了解 1.就是写在成员位置的代码块可以优先于构造方法执行 2.作用可以把多个构造方法中重复的代码抽取出来。 3.执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法 这个技术现在也渐渐淘汰了 可以将重复的代码抽取成一个方法构造方法需要使用时直接调用方法就行了。
静态代码块重点 就是在构造代码块的基础上加上static 小结
6.6 抽象类和抽象方法
抽象类 下面每个子类的工作内容是不一样的解决方法就是在子类中随便写一个方法乙让子类再去重写。
但是有一个小弊端下面的子类是别人写的代码别人在写子类的时候忘了重写那就没办法了。
所以抽象关键字就来进行强制重写否则代码就直接报错抽象方法所在的类就叫抽象类。
抽象关键字abstract
抽象类 如果一个类中存在抽象方法那么该类就必须声明为抽象类。由方法推向类不是由类推向方法
抽象方法 抽象方法的定义格式 public abstract 返回值类型 方法名(参数列表); 没有方法体
抽象类的定义同理public abstract class 类名{}
抽象类和抽象方法的注意事项 1.抽象类不能创建对象
2.抽象类中不一定有抽象方法有抽象方法的一定是抽象类
3.抽象类可以有构造方法作用当创建子类对象时给子类的属性进行赋值
4.抽象类的子类分两种情况
如果子类不是抽象类则需要重写抽象类中的所有方法如果子类是抽象类则没事 ieda便捷键 alt回车 可以查看报错的内容并且快速修改 练习
Animal类
public abstract class Animal {private String name;private int age;public Animal() {}public Animal(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 void drink(){System.out.println(动物在喝水);}public abstract void eat();
}Frog类
public class Frog extends Animal{public Frog() {}public Frog(String name, int age) {super(name, age);}Overridepublic void eat() {System.out.println(青蛙在吃虫子);}
}Dog类
public class Dog extends Animal{public Dog(){}public Dog(String name, int age) {super(name, age);}Overridepublic void eat() {System.out.println(狗吃骨头);}
}Sheep类
public class Sheep extends Animal{public Sheep() {}public Sheep(String name, int age) {super(name, age);}Overridepublic void eat() {System.out.println(山羊在吃草);}
}测试类
public class Test {public static void main(String[] args) {//创建对象Frog f new Frog(mauga,1);System.out.println(f.getName(),f.getAge());f.drink();f.eat();}
}抽象类和抽象方法的意义 当每个关于同一个行为的代码不统一时调用时就会非常痛苦 用抽象类进行重写 总结
6.7 接口
接口就是一种规则是指父类与子类之间的关系。 下述图片很好的说明了为什么要有接口
接口的应用 接口不代表一类事务他代表一种规则是对行为的抽象 接口与抽象的区别 抽象更多是表示一类事物而接口更多表示行为 接口的定义和使用 1.接口用关键字interface定义 public interface 接口名{}
2.接口不能创建对象
3.接口和类是实现关系通过inplements关键字表示 public class 类名 inplements 接口名{}
4.接口的子类接口的实现类 分两种情况
不是抽象类直接重写所有抽象方法更多用这种是抽象类没事
5.接口里的方法都是抽象方法 练习 创建新的类时选择接口的选项
Animal类
public abstract class Animal {private String name;private int age;public Animal() {}public Animal(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 abstract void eat();
}接口
public interface Swim {public abstract void swim();
}Rabbit类
public class Rabbit extends Animal{public Rabbit() {}public Rabbit(String name, int age) {super(name, age);}Overridepublic void eat() {System.out.println(兔子在吃胡萝卜);}
}Frog类
public class Frog extends Animal implements Swim{public Frog() {}public Frog(String name, int age) {super(name, age);}Overridepublic void eat() {System.out.println(青蛙在吃虫子);}Overridepublic void swim() {System.out.println(青蛙在蛙泳);}
}Dog类
public class Dog extends Animal implements Swim{public Dog() {}public Dog(String name, int age) {super(name, age);}Overridepublic void eat() {System.out.println(狗吃骨头);}Overridepublic void swim() {System.out.println(狗刨式);}
}测试类
public class Test {public static void main(String[] args) {Frog f new Frog(青蛙,1);System.out.println(f.getName(), f.getAge());f.eat();f.swim();Rabbit r new Rabbit(兔子,2);System.out.println(r.getName(),r.getAge());r.eat();}
}6.7.1 接口的细节成员特点和各种接口的关系
接口中成员的特点
inter接口
public interface Inter {//public static finalint a 10;//public abstractvoid method();
}InterImp1类
public class InterImp1 implements Inter{Overridepublic void method() {System.out.println(method);}
}测试类
import java.util.Scanner;public class Test {public static void main(String[] args) {//创建实现对象并调用方法InterImp1 li new InterImp1();li.method();Scanner sc new Scanner(System.in);sc.next();//防止程序运行过快无法反应}
}接口和类之间的关系
类和类之间的关系 继承关系只能单继承不能多继承但是可以多重继承类和接口的关系 实现关系可以单实现也可以多实现还可以在继承一个类的同时实现多个接口。 多个接口中有重名的方法只需在类里重写一次就行了接口与接口之间的关系 继承关系可以单继承也可以多继承。 如果实现类实现了子接口那么就需要重写所有的抽象方法
//如果实现类实现了子接口那么就需要重写所有的抽象方法
//接口1
public interface Inter1{public abstract void method1();
}
//接口2
public interface Inter2{public abstract void method2();
}
//接口3
public interface Inter3 extends Inter1,Inter2{public abstract void method3();
}
//实现类
public class InterImpl implements Inter3{Overridepublic void method1(){}Overridepublic void method2(){}Overridepublic void method3(){}
}总结
6.7.2 接口和抽象类案例 流程图思路 1.
2.最优流程图
//因为直接创建人的对象是没有意义的所以直接把person创建为抽象类
public abstract class Person {private String name;private int age;public Person() {}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;}
}
---------------------------------------------------
package com.inherit4.study;public abstract class athletes extends Person{public athletes() {}public athletes(String name, int age) {super(name, age);}public abstract void study();
}
---------------------------------------------------
package com.inherit4.study;public abstract class instructor extends Person{public instructor() {}public instructor(String name, int age) {super(name, age);}public abstract void teach();
}
---------------------------------------------------
package com.inherit4.study;public interface English {public abstract void eng();
}
---------------------------------------------------
package com.inherit4.study;public class ppathletes extends athletes implements English{public ppathletes() {}public ppathletes(String name, int age) {super(name, age);}Overridepublic void eng() {System.out.println(说英语);}Overridepublic void study() {System.out.println(学打乒乓球);}
}
---------------------------------------------------
package com.inherit4.study;public class bkathletes extends athletes{public bkathletes() {}public bkathletes(String name, int age) {super(name, age);}Overridepublic void study() {System.out.println(学打篮球);}
}
---------------------------------------------------
package com.inherit4.study;public class ppInstuctor extends instructor implements English{public ppInstuctor() {}public ppInstuctor(String name, int age) {super(name, age);}Overridepublic void eng() {System.out.println(说英语);}Overridepublic void teach() {System.out.println(教打乒乓球);}
}
---------------------------------------------------
package com.inherit4.study;public class bkInstucttor extends instructor{public bkInstucttor() {}public bkInstucttor(String name, int age) {super(name, age);}Overridepublic void teach() {System.out.println(教打篮球);}
}
---------------------------------------------------
package com.inherit4.study;public class test {public static void main(String[] args) {ppathletes panew ppathletes(zhangsan,18);System.out.println(pa.getName() pa.getAge());pa.eng();pa.study();bkathletes banew bkathletes(zhangsi,19);System.out.println(ba.getName() ba.getAge());ba.study();ppInstuctor pinew ppInstuctor(lisi,30);System.out.println(pi.getName() pi.getAge());pi.eng();pi.teach();bkInstucttor binew bkInstucttor(zhangliu,36);System.out.println(bi.getName() bi.getAge());bi.teach();}
}6.7.3 接口的新增方法
jdk7以前接口中只能定义抽象方法 jdk8以后接口中可以定义有方法体的方法默认静态 jdk9以后接口中可以定义私有方法 即jdk8之后接口里的方法可以有方法体了 我又想加新的规则;又想让他们的代码不报错怎么办呢? jdk8以后接口中新增的默认方法
允许在接口中定义默认方法需要使用关键字default修饰 作用解决接口升级的问题
接口默认方法的定义格式 public default 返回值类型 方法名(参数列表){方法体} 例如
public default void show(){}接口中默认方法的注意事项:
接口中的默认方法不是抽象方法所以不强制重写。如果被重写重写时去掉default 关键字。public可以省略default不能省略如果实现了多个接口多个接口中存在相同名字的默认方法子类就必须对该方法进行重写。
接口A:
public interface InterA {public abstract void method();public default void show(){System.out.println(InterA接口中的默认方法----show);}
}接口B
public interface InterB {public default void show(){System.out.println(InterB接口中的默认方法----show);}
}InterImpl:
public class InterImpl implements InterA,InterB{Overridepublic void method() {}Overridepublic void show() {InterA.super.show();}
}测试类
public class Test {public static void main(String[] args) {InterImpl ii new InterImpl();ii.show();}
}jdk8以后接口中新增的静态方法
jdk8以后接口中新增的方法静态方法 静态方法不能重写。 允许在接口中定义静态方法需要使用关键字static修饰
接口静态方法的定义格式 public static 返回值类型 方法名(参数列表){方法体} 例如
public static void show(){}接口中静态方法的注意事项:
接口中的静态方法只能通过接口名调用不能通过实现类名或者对象名调用public可以省略static不能省略
重写的概念
jdk9新增的私有方法 为什么在接口中增加私有方法? 对于一些重复代码是对单独一个接口中其他方法去服务的不想被外类去访问因为外类访问是没有意义的因此在接口中出现了私有方法 接口中私有方法的定义格式 格式1private 返回值类型 方法名(参数列表){}不加default关键字给默认方法服务即默认方法中的重复代码 例如
private void show(){}格式2private static 返回值类型 方法名(参数列表){}给静态方法服务即静态方法中的重复代码 例如
private static void method(){}小结
6.7.4 接口应用 把多个类都有可能用到的规则定义成接口对实现类来讲想要要实现类拥有什么样的功能就实现对应的接口就行了。 即接口代表规则是行为的抽象。想要让哪个类拥有一个行为就让这个类实现对应的接口就行了当一个方法的参数是接口时可以传递接口所有实现类的对象这种方式称之为接口多态。 小结 6.7.5 适配器设计模型
设计模式 设计模式是一套被反复利用多数人知晓的经过分类编目的代码设计经验的总结。使用设计模式是为了可重用代码让代码更容易被他人理解保证代码可靠性程序的重用性。 简单理解设计模式就是各种套路
适配器设计模式
解决接口与接口实现类之间的矛盾问题 就是在接口和实现类中间加上一个单独的类这个类把接口里的所有方法重写空着然后实现类使用时只需要重写需要的方法就行了
注意中间类的名字是XXXAdapder
接口
中间类
实现类继承中间的适配器不让外界创建它的对象
总结
6.8 初始内部类
类的五大成员 属性方法构造方法代码块内部类 内部类就是在一个类里再定义的类 例如
public class Person{public class Student{}
}为什么要学习内部类 代码实现
内部类的分类 分为
成员内部类静态内部类局部内部类匿名内部类 前三种了解一下哎写代码时能看懂会用就行最后一种匿名内部类需要掌握 person类里的student就是内部类person就是外部类 跟这两个类无关的其他所有类就是外部其他类
定义内部类的规则 内部类表示的事物是外部类的一部分 内部类单独出现没有任何意义内部类的访问特点 内部类可以直接访问外部类的成员包括私有的 外部类要访问内部类的成员必须在外部类里创建对象
案例
总结
6.8.1 成员内部类
写在成员位置的内部类就是成员内部类
public class Car {private String carName;private int carAge;private String carColor;eng nengnew eng();public void show2(){System.out.println(neng.engAge neng.engName neng.engColor);}class eng{//这里就是成员内部类String engName;int engAge;String engColor;public void show1(){System.out.println(carName carAge carColor);}}
}成员内部类代码的书写 1.写在成员位置的属于外部类的成员有着成员的性质 2.成员内部类可以被一些修饰符所修饰比如private默认protectedpublicstatic用static修饰的内部类就不是成员内部类了是静态内部类 3.成员内部类里可以定义静态变量jdk16以后
成员内部类的创建
方式1private修饰时会使用 在外部类中编写方法对外提供内部类的对象可以用Object创建一个先对象来接收内部类对象的返回值也可以直接使用
注意版本要匹配
方式1的例子
public class Outer {private String name;private class Inner{}public Inner getInner(){//创建方法return new Inner();}
}
Outer onew Outer();
o.getInner();//调用方法方式2 直接创建格式外部类名.内部类名 对象名外部类对象(new 对象).内部类对象(new 对象);
//这里相当于内部类是外部类的成员创建外部类对象后调用
Outer.Inner duixiang new Outer().new Inner();
//这里Outer是外部类名Inner是内部类名成员内部类获取外部类的成员变量使用Outer.this.变量,Outer是外部类名
练习 内存图解析
Outer类
public class Outer {private int a 10;class Inner{private int a 20;public void show(){int a 30;System.out.println(Outer.this.a);System.out.println(this.a);System.out.println(a);}}
}测试类
public class Test {public static void main(String[] args) {//创建内部类的对象并调用show方法Outer.Inner oi new Outer().new Inner();oi.show();}
}小结
6.8.2 静态内部类 例子
public class Outer {int a10;static String name111;//静态内部类static class Inner{public void show1(){Outer oinew Outer();sout(oi.a);//外部类的非静态对象需要创建对象才能访问sout(name);//外部类的静态变量可以直接访问}public static void show2(){Outer oinew Outer();sout(oi.a);//外部类的非静态对象需要创建对象才能访问sout(name);//外部类的静态变量可以直接访问} }
}创建静态内部类的语法 外部类名.内部类名 对象名new 外部类名.内部类名(); 例如 Outer.Inner oinew Outer.Inner();(这里new的是Inner)用静态内部类对象调用静态内部类中的非静态方法 先创建对象用对象调用调用静态内部类中的静态方法 直接调用Outer.Inner.方法名()
案例
public class Outer {//静态内部类static class Inner{public void show1(){sout(非静态的方法被调用了);}public static void show2(){sout(静态的方法被调用了);} }
}
//调用
//调用静态内部类里的非静态的方法需要先创建一个静态内部类对象然后用对象调用
Outer.Inner oinew Outer.Inner();
oi.show1();
//调用静态内部类里的静态的方法可以直接通过 外部类.内部类.方法名() 调用
Outer.Inner.show2();小结
6.8.3 局部内部类 案例
Outer类
public class Outer {int b20;public void show(){int a10;//局部内部类class Inner{String name;int age;public void method1(){System.out.println(a);System.out.println(b);System.out.println(局部内部类中的method1方法);}public static void method2(){System.out.println(局部内部类中的method2静态方法);}}//创建局部内部类的对象Inner i new Inner();System.out.println(i.name);//nullSystem.out.println(i.age);//0i.method1();Inner.method2();}
}测试类
public class Test {public static void main(String[] args) {Outer o new Outer();o.show();}
} 6.8.4 匿名内部类
匿名内部类的本质就是隐藏了名字的内部类可以写在成员位置也可以写在局部位置 匿名内部类有三个特点 1.实现或继承关系 2.方法的重写 3.创建对象
匿名内部类的语法
new 类名或接口名(){重写方法();//类或接口的抽象方法的重写
};
//这一段代码的返回值是一个对象可以被对象变量接收例如
new Inter(){public void show(){}
};即
new Swim(){//这里的new创建的是后面没有名字的类的对象Overridepublic void swim(){sout(重写的游泳方法);}
};
/*这一部分从语法上来解释应该叫做匿名内部类的对象
new Swim(){Overridepublic void swim(){sout(重写的游泳方法);}
};
*/
/*这一部分才是没有名字类的主体即匿名内部类实现了Swim这个接口
{Overridepublic void swim(){sout(重写的游泳方法);}
};*/
以上代码有三个特点
1.实现关系2.方法的重写3.创建对象
同理当Swim换成一个类名时特点就变为了
1.继承关系
2.方法的重写
3.创建对象此时匿名内部类的主题就是父类的子类
new Fulei(){//这里的new创建的是后面没有名字的类的对象Overridepublic void show(){sout(重写的show方法);}
};
/*这一部分从语法上来解释应该叫做匿名内部类的对象
new Fulei(){Overridepublic void show(){sout(重写的show方法);}
};
*/
/*这一部分才是没有名字类的主体即匿名内部类继承了Fulei的子类
{Overridepublic void show(){sout(重写的show方法);}
};*/
应用场景 可以作为方法的实参不用再写格外的类
比如
//Animal类父类
public abstract class Animal{public void eat(){sout(吃东西)}
}
//Dog类子类
public class Dog extends Animal{Overridepublic void eat(){sout(狗吃骨头)}
}
//测试类
psvm(String[] args){//以前调用method方法Dog dnew Dog();method(d);//使用匿名内部类调用method方法method(new Animal(){Overridepublic void eat(){sout(狗吃骨头)}}
)
/*
new Animal(){Overridepublic void eat(){sout(狗吃骨头)}}这个整体就相当于Animal a子类对象 即多态
*/public static void method(Animal a){a.eat();}
}拓展 可以直接用语法的形式调用对象 同理
new Fulei(){//这里的new创建的是后面没有名字的类的对象Overridepublic void show(){sout(重写的show方法);}
}.show();//所以可以调用自己里面的方法小结 文章转载自: http://www.morning.nqbcj.cn.gov.cn.nqbcj.cn http://www.morning.ylzdx.cn.gov.cn.ylzdx.cn http://www.morning.qsbcg.cn.gov.cn.qsbcg.cn http://www.morning.pqnpd.cn.gov.cn.pqnpd.cn http://www.morning.ctlzf.cn.gov.cn.ctlzf.cn http://www.morning.pqjpw.cn.gov.cn.pqjpw.cn http://www.morning.xbnkm.cn.gov.cn.xbnkm.cn http://www.morning.hnmbq.cn.gov.cn.hnmbq.cn http://www.morning.shxrn.cn.gov.cn.shxrn.cn http://www.morning.fkmqg.cn.gov.cn.fkmqg.cn http://www.morning.jhkzl.cn.gov.cn.jhkzl.cn http://www.morning.kfrhh.cn.gov.cn.kfrhh.cn http://www.morning.prxqd.cn.gov.cn.prxqd.cn http://www.morning.bwttp.cn.gov.cn.bwttp.cn http://www.morning.brps.cn.gov.cn.brps.cn http://www.morning.ygwyt.cn.gov.cn.ygwyt.cn http://www.morning.llxns.cn.gov.cn.llxns.cn http://www.morning.bangaw.cn.gov.cn.bangaw.cn http://www.morning.tfgkq.cn.gov.cn.tfgkq.cn http://www.morning.rjcqb.cn.gov.cn.rjcqb.cn http://www.morning.rzcbk.cn.gov.cn.rzcbk.cn http://www.morning.mywnk.cn.gov.cn.mywnk.cn http://www.morning.zrdhd.cn.gov.cn.zrdhd.cn http://www.morning.fpkdd.cn.gov.cn.fpkdd.cn http://www.morning.rgnp.cn.gov.cn.rgnp.cn http://www.morning.jfqpc.cn.gov.cn.jfqpc.cn http://www.morning.gbybx.cn.gov.cn.gbybx.cn http://www.morning.nhpmn.cn.gov.cn.nhpmn.cn http://www.morning.wzjhl.cn.gov.cn.wzjhl.cn http://www.morning.dspqc.cn.gov.cn.dspqc.cn http://www.morning.enjoinfo.cn.gov.cn.enjoinfo.cn http://www.morning.drggr.cn.gov.cn.drggr.cn http://www.morning.pngdc.cn.gov.cn.pngdc.cn http://www.morning.mrfbp.cn.gov.cn.mrfbp.cn http://www.morning.rckmz.cn.gov.cn.rckmz.cn http://www.morning.yrwqz.cn.gov.cn.yrwqz.cn http://www.morning.tqxtx.cn.gov.cn.tqxtx.cn http://www.morning.mhmsn.cn.gov.cn.mhmsn.cn http://www.morning.sbrpz.cn.gov.cn.sbrpz.cn http://www.morning.njntp.cn.gov.cn.njntp.cn http://www.morning.gxtbn.cn.gov.cn.gxtbn.cn http://www.morning.wpcfh.cn.gov.cn.wpcfh.cn http://www.morning.cbmqq.cn.gov.cn.cbmqq.cn http://www.morning.jfmyt.cn.gov.cn.jfmyt.cn http://www.morning.ptzbg.cn.gov.cn.ptzbg.cn http://www.morning.dspqc.cn.gov.cn.dspqc.cn http://www.morning.fbqr.cn.gov.cn.fbqr.cn http://www.morning.dztp.cn.gov.cn.dztp.cn http://www.morning.slysg.cn.gov.cn.slysg.cn http://www.morning.hgtr.cn.gov.cn.hgtr.cn http://www.morning.snnb.cn.gov.cn.snnb.cn http://www.morning.skksz.cn.gov.cn.skksz.cn http://www.morning.khtyz.cn.gov.cn.khtyz.cn http://www.morning.chxsn.cn.gov.cn.chxsn.cn http://www.morning.qscsy.cn.gov.cn.qscsy.cn http://www.morning.plqhb.cn.gov.cn.plqhb.cn http://www.morning.slkqd.cn.gov.cn.slkqd.cn http://www.morning.nafdmx.cn.gov.cn.nafdmx.cn http://www.morning.gjmll.cn.gov.cn.gjmll.cn http://www.morning.dfojgo.cn.gov.cn.dfojgo.cn http://www.morning.ghyfm.cn.gov.cn.ghyfm.cn http://www.morning.gzttoyp.com.gov.cn.gzttoyp.com http://www.morning.qsswb.cn.gov.cn.qsswb.cn http://www.morning.yrhpg.cn.gov.cn.yrhpg.cn http://www.morning.ttkns.cn.gov.cn.ttkns.cn http://www.morning.fkrzx.cn.gov.cn.fkrzx.cn http://www.morning.krjyq.cn.gov.cn.krjyq.cn http://www.morning.zwgbz.cn.gov.cn.zwgbz.cn http://www.morning.gynkr.cn.gov.cn.gynkr.cn http://www.morning.hqpyt.cn.gov.cn.hqpyt.cn http://www.morning.tslxr.cn.gov.cn.tslxr.cn http://www.morning.kxrhj.cn.gov.cn.kxrhj.cn http://www.morning.xsfg.cn.gov.cn.xsfg.cn http://www.morning.qrnbs.cn.gov.cn.qrnbs.cn http://www.morning.gwxwl.cn.gov.cn.gwxwl.cn http://www.morning.fnczn.cn.gov.cn.fnczn.cn http://www.morning.yqqxj26.cn.gov.cn.yqqxj26.cn http://www.morning.jmmz.cn.gov.cn.jmmz.cn http://www.morning.mtyhk.cn.gov.cn.mtyhk.cn http://www.morning.tbknh.cn.gov.cn.tbknh.cn