首页
统计
友链
关于
Search
1
静静地生活着
415 阅读
2
JVM_1.引言
405 阅读
3
Chapter 03
331 阅读
4
机器学习 01
323 阅读
5
欢迎使用 Typecho
283 阅读
Java
School
ML
Other
Share
Explore
运维
登录
Search
bbchen
累计撰写
53
篇文章
累计收到
5
条评论
首页
栏目
Java
School
ML
Other
Share
Explore
运维
页面
统计
友链
关于
搜索到
53
篇与
的结果
2023-02-26
Chapter13_常用类
常用类本章内容包装类 Wrapper针对八种基本数据类型相应的引用类型——包装类有了类的特点,就可以调用类中的方法包装类和基本数据类型的转换jdk5 前的手动装箱和拆箱方式,装箱:基本类型 -> 包装类型,反正为拆箱jdk5 以后(含 jdk5)的自动装箱和拆箱方式自动装箱底层调用的是 valueOf 方法,比如 Integer.valueOf()package com.bbedu.wrapper; public class Integer01 { public static void main(String[] args) { // 演示 in Integer 的装箱和拆箱 // jdk5 之前手动 int n1 = 100; Integer integer = new Integer(n1); Integer integer1 = Integer.valueOf(n1); int i = integer.intValue(); // jdk5 后自动装箱拆箱 int n2 = 500; Integer integer2 = n2; // 底层是Integer.valueOf(n2) int n3 = integer2; // 底层是intValue()方法 Object obj1 = true ? new Integer(1) : new Double(2.0); System.out.println(obj1); } }包装类和 String 类的转换package com.bbedu.wrapper; public class WrapperVSString { public static void main(String[] args) { Integer i = 100; // Integer -> String // 方式1 String str1 = i + ""; // 方式2 String str2 = i.toString(); // 方式3 String str3 = String.valueOf(i); // String -> Integer String str4 = "12345"; // 方式1 Integer i2 = Integer.parseInt(str4); // 使用到自动装箱 // 方式2 Integer i3 = new Integer(str4); // 构造器 } }包装类的常用方法很多,使用时查阅即可Integer 细节falsetruefalse此处关键词:IntegerCacheString 类String 对象用于保存字符串,也就是一组字符序列字符串常量对象是用双引号括起的字符序列,例如:"你好","Hello",”5.21”等字符串的字符使用Unicode字符编码,一个字符占两个字节String 类有很多构造器,构造器重载:常用的有:String s2 = new String(String original);String s3 = new String(char[] a);String s4 = new String(char[] a,int startIndex,int count);String s5 = new String(byte[] b);String 类实现了 Serializable 接口,可以串行化,可以在网络传输实现了 Comparable 接口,可以相互比较大小String 是 final 类,不能被继承String 有一个 private final char value[]; 用于存放字符串内容,一定要注意,value 是一个 final 类型,不可修改(即 value 不能指向新的地址,但是单个字符的内容可以变化)创建 String 对象的两种方式方式一:直接赋值: String s = "bbedu"方式二:调用构造器:String s = new String("bbedu");区别方式一:先从常量池查看是否有"bbedu"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s 最终指向的是常量池的空间地址方式二:先在堆中创建空间,里面维护了 value 属性,指向常量池的bbedu空间,如果常量池没有"bbedu",重新创建,如果有直接通过 value 指向,最终指向的是堆中的空间地址练习T F T Fb.intern() 方法最终返回的是常量池的地址F T T FT T T F三个对象:如图所示T T输出:hsp and havaString 类的常用方法String 类是保存字符串常量的,每次更新都需要重新开辟空间,效率较低,因此 java 设计者还提供了 StringBuilder 和 StringBuffer 来增强 String 的功能,并提高效率。package com.bbedu.string_; public class StringMethod01 { public static void main(String[] args) { // 1.equals String str1 = "hello"; String str2 = "Hello"; System.out.println(str1.equals(str2)); // false // 2. equalsIgnoreCase String username = "John"; if("john".equalsIgnoreCase(username)){ System.out.println("Success"); }else { System.out.println("Failure"); } // 3.length System.out.println("bbchen".length()); // 4.indexOf String s1 = "we@th@er"; System.out.println(s1.indexOf('@')); System.out.println(s1.indexOf("we")); System.out.println(s1.indexOf('#')); // 5.lastIndexOf System.out.println(s1.lastIndexOf('@')); System.out.println(s1.lastIndexOf('#')); // 6.substring String name = "hello,world"; System.out.println(name.substring(6)); System.out.println(name.substring(0, 5)); } }package com.bbedu.string_; public class StringMethod02 { public static void main(String[] args) { // 1.toUpperCase String s = "hello"; System.out.println(s.toUpperCase()); // 2.toLowerCase System.out.println(s.toLowerCase()); // 3.concat String s1 = ",world"; System.out.println(s.concat(s1)); // 4.replace String str = "bb want to be Java developer"; System.out.println(str.replace("Java", "Python")); System.out.println(str); // 5.split String poem = "锄禾日当午,汗滴禾下土"; String[] split = poem.split(","); for (String value : split) { System.out.println(value); } // 6.toCharArray String s2 = "happy"; char[] chs = s2.toCharArray(); for (char ch : chs) { System.out.println(ch); } // 7.compareTo String a = "jr"; String b = "jack"; System.out.println(a.compareTo(b)); System.out.println('r' - 'a'); // 8.format String name = "john"; String age = "10"; double score = 84.5 / 3; char gender = '男'; String formatStr = "我的名字是%s, 今年%d岁, 得分为%.2f, 性别为%c"; String info = String.format(formatStr, name, Integer.parseInt(age), score, gender); System.out.println(info); } }StringBuffer 类java.lang.StringBuffer 代表可变的字符序列,可以对字符串内容进行增删很多方法和 String 相同,但 StringBuffer 是可变长度的StringBuffer 是一个容器String vs StringBufferString 保存的是字符串常量,里面的值不能更改,每次 String 类的更新实际上就是更改地址,效率较低 //private final byte[] value;StringBuffer 保存的是字符串变量,里面的值可以更改,每次StringBuffer 的更新实际上可以更新内容,不用每次更新地址,效率较高 //byte[] value;String 和 StringBuffer 互相转换package com.bbedu.stringbuffer_; public class StringBuffer01 { public static void main(String[] args) { String str = "hello tim"; // String -> StringBuffer // 方式1 StringBuffer stringBuffer1 = new StringBuffer(str); // 方式2 StringBuffer stringBuffer = new StringBuffer("hello"); stringBuffer = stringBuffer.append(str); // StringBuffer -> String StringBuffer bbchen = new StringBuffer("bbchen"); // 方式1.toString String s = bbchen.toString(); // 方式2.构造器 String s1 = new String(bbchen); } }常见方法package com.bbedu.stringbuffer_; public class StingBufferMethod { public static void main(String[] args) { StringBuffer hello = new StringBuffer("hello"); // 1.append hello.append(','); hello.append("world"); System.out.println(hello); // 2.delete hello.delete(2, 4); // 删除下标[2,4)的字符 System.out.println(hello); // 3.replace hello.replace(4, 9, "bbchen"); System.out.println(hello); // 4.indexOf int index = hello.indexOf("e"); System.out.println(index); // 5.insert hello.insert(10, "gogogo"); System.out.println(hello); // 6.length System.out.println(hello.length()); } }StringBuilder 类StringBuilder 继承 AbstractStringBuilder 类实现了 Serializable,说明 StringBuilder 对象是可以串行化StringBuilder 是 final 类,不能被继承StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder 的 byte[] value,因此字符序列是在堆中StringBuilder 的方法,没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用 StringBuilderString, StringBuffer 和 StringBuilder 的比较StringBuilder 和 StriBuffer 非常相似,均代表可变的字符序列,而且方法也一样String: 不可变字符序列,效率低,但是复用率高StringBuffer: 可变字符序列、效率较高、线程安全StringBuilder: 可变字符序列、效率最高、线程不安全String 使用说明:如果我们对 String 做大量修改,不要使用 String结论如果字符串存在大量的修改操作,一般使用StringBuffer 或StringBuilder如果字符串存在大量的修改操作,并在单线程的情况,使用 StringBuilder如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer如果我们字符串很少修改,被多个对象引用,使用String, 比如配置信息等StringBuilder的方法使用和 StringBuffer一样,不再赘述Math 类package com.bbedu.math_; import java.io.FilterOutputStream; public class MathMethod { public static void main(String[] args) { // 5.round long round = Math.round(5.51); System.out.println(round); // 6.sqrt double sqrt = Math.sqrt(9); System.out.println(sqrt); // 7.random 返回 [0, 1) 直接的随机小数 for (int i = 0; i < 10; i++) { //返回 [2, 7] 的随机整数 System.out.println((int)(Math.random() * 6 + 2)); } // max, min int min = Math.min(1, 9); int max = Math.max(4, 20); System.out.println(min); System.out.println(max); } }Arrays 类Comparator原理:while (left < right) { int mid = (left + right) >>> 1; if (c.compare(pivot, a[mid]) < 0) right = mid; else left = mid + 1; }package com.bbedu.arrays_; import java.util.Arrays; import java.util.Comparator; public class ArrayMethod01 { public static void main(String[] args) { // toString Integer[] integers = {1, 20, 90}; System.out.println(Arrays.toString(integers)); // sort Integer[] arr = {1, -1, 31, 3, 2, 53, 9, 20}; Arrays.sort(arr); // 默认排序方法 // 定制排序, 体现接口编程的方式 Arrays.sort(arr, new Comparator<Integer>() { // 匿名内部类 @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }); System.out.println("Sorted:"); System.out.println(Arrays.toString(arr)); } }package com.bbedu.arrays_; import java.util.Arrays; import java.util.Comparator; public class ArraysSortCustom { public static void main(String[] args) { int[] arr = {0, -3, 20, 14, 23, 43, 21}; System.out.println(Arrays.toString(arr)); bubble02(arr, new Comparator() { @Override public int compare(Object o1, Object o2) { int i1 = (Integer) o1; int i2 = (Integer) o2; return i2 - i1; } }); System.out.println(Arrays.toString(arr)); } // 使用冒泡排序 public static void bubble01(int[] arr){ int temp = 0; for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - i - 1; j++) { if(arr[j] > arr[j + 1]){ temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } // 结合冒泡 + 定制 public static void bubble02(int[] arr, Comparator c){ int temp = 0; for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - i - 1; j++) { // c if(c.compare(arr[j], arr[j + 1]) > 0){ temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } }package com.bbedu.arrays_; import java.util.Arrays; import java.util.List; public class ArraysMethod02 { public static void main(String[] args) { Integer[] arr = {1, 3, 5, 23, 100, 854, 1145}; // 二分查找,要求数组有序 // 不存在返回 return -(low + 1); // key not found. int index = Arrays.binarySearch(arr, -23); System.out.println(index); // copyOf // 拷贝长度 > arr.length ,在数组后加 null Integer[] newArr = Arrays.copyOf(arr, arr.length + 1); System.out.println(Arrays.toString(newArr)); // fill 数组填充 Integer[] num = new Integer[]{9, 3, 2}; Arrays.fill(num, 99); System.out.println(Arrays.toString(num)); // equals 比较两数组是否完全一样,区分顺序 Integer[] arr2 = {3, 1, 5, 23, 100, 854, 1145}; boolean equals = Arrays.equals(arr, arr2); System.out.println(equals); // asList List<Integer> integers = Arrays.asList(2, 3, 4, 5, 6, 1); System.out.println(integers); System.out.println(integers.getClass()); } }练习package com.bbedu.arrays_; import java.util.Comparator; @SuppressWarnings("all") public class ArraysExercise { public static void main(String[] args) { Book[] books = new Book[4]; books[0] = new Book("红楼梦", 100); books[1] = new Book("金瓶梅", 90); books[2] = new Book("三体", 60); books[3] = new Book("毛泽东选集", 300); for (int i = 0; i < books.length; i++) { System.out.println(books[i].toString()); } // 按价格 // Book.sort(books, new Comparator() { // @Override // public int compare(Object o1, Object o2) { // Book i1 = (Book) o1; // Book i2 = (Book) o2; // // // 返回类型不一致,进行转换 // double priceVal = i2.getPrice() - i1.getPrice(); // if(priceVal > 0) { // return -1; // } else if (priceVal < 0) { // return 1; // }else { // return 0; // } // } // }); // 按照书名从长到短 Book.sort(books, new Comparator() { @Override public int compare(Object o1, Object o2) { Book i1 = (Book) o1; Book i2 = (Book) o2; return i1.getName().length() - i2.getName().length(); } }); System.out.println("====排序后===="); for (int i = 0; i < books.length; i++) { System.out.println(books[i].toString()); } } } @SuppressWarnings("all") class Book { private String name; private double price; public Book(String name, double price) { this.name = name; this.price = price; } 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; } @Override public String toString() { return "Book{" + "name='" + name + '\'' + ", price=" + price + '}'; } public static void sort(Book[] b, Comparator c){ Book book = null; for (int i = 0; i < b.length - 1; i++) { for (int j = 0; j < b.length - i - 1; j++) { // 定义接口, 根据价格排序 if(c.compare(b[j], b[j + 1]) < 0){ book = b[j]; b[j] = b[j + 1]; b[j + 1] = book; } } } } }System 类package com.bbedu.system_; import java.util.Arrays; public class System_ { public static void main(String[] args) { // // exit 0为正常状态 // System.out.println("ok1"); // System.exit(0); // System.out.println("ok2"); // arraycopy // * @param src the source array. // * @param srcPos starting position in the source array. // * @param dest the destination array. // * @param destPos starting position in the destination data. // * @param length the number of array elements to be copied. int[] arr1 = {1, 2, 3}; int[] arr2 = new int[3]; System.arraycopy(arr1, 0, arr2, 1, 2); System.out.println(Arrays.toString(arr2)); System.out.println(System.currentTimeMillis()); } }BigInteger 和 BigDecimal 类package com.bbedu.bignum; import java.math.BigInteger; public class BigInteger_ { public static void main(String[] args) { // 数字太大,需要使用 BigInteger 类 // long l = 233333333333333333333333333333L; BigInteger bigInteger = new BigInteger("23333333333333333333333333"); BigInteger bigInteger1 = new BigInteger("1000000"); System.out.println(bigInteger); // 加减乘除使用对应方法 System.out.println(bigInteger.add(bigInteger1)); System.out.println(bigInteger.subtract(bigInteger1)); System.out.println(bigInteger.divide(bigInteger1)); System.out.println(bigInteger.multiply(bigInteger1)); } }package com.bbedu.bignum; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; public class BigDecimal_ { public static void main(String[] args) { double d = 1111.1111111111119999999999999999; System.out.println(d); // 需要保存精度很高的数时,使用 BigDecimal BigDecimal bigDecimal = new BigDecimal("1111.1111111111119999999999999999"); System.out.println(bigDecimal); // 加减乘除需要使用特定方法 BigDecimal bigDecimal1 = new BigDecimal("100.9999999999"); System.out.println(bigDecimal.add(bigDecimal1)); System.out.println(bigDecimal.subtract(bigDecimal1)); System.out.println(bigDecimal.divide(bigDecimal1, RoundingMode.CEILING)); //可能异常:ArithmeticException: Non-terminating decimal System.out.println(bigDecimal.multiply(bigDecimal1)); } }日期类package com.bbedu.date_; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class Date01 { public static void main(String[] args) throws ParseException { // 过去当前系统时间,通常需要格式转换 Date d1 = new Date(); System.out.println(d1); System.out.println(d1.getTime()); Date date = new Date(92345678); System.out.println(date); // 参见手册 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E"); String format = simpleDateFormat.format(d1); System.out.println(format); // 字符串转 Date String s = "2022年10月13日 02:33:02 周四"; Date parse = simpleDateFormat.parse(s); System.out.println(parse); } }package com.bbedu.date_; import java.util.Calendar; public class Calendar_ { public static void main(String[] args) { Calendar c = Calendar.getInstance(); System.out.println("c=" + c); // 需要自己组合: System.out.println("年:" + c.get(Calendar.YEAR)); System.out.println("月:" + (c.get(Calendar.MONTH)+1)); // 月从0开始 System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH)); } }package com.bbedu.date_; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; public class LocalDate_ { public static void main(String[] args) { // 第三代日期 LocalDateTime now = LocalDateTime.now(); System.out.println(now); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String format = dateTimeFormatter.format(now); System.out.println(format); System.out.println("年=" + now.getYear()); System.out.println("月=" + now.getMonthValue()); System.out.println("月=" + now.getMonth()); System.out.println("日=" + now.getDayOfMonth()); System.out.println("时=" + now.getHour()); System.out.println("分=" + now.getMinute()); System.out.println("秒=" + now.getSecond()); LocalDate now1 = LocalDate.now(); LocalTime now2 = LocalTime.now(); System.out.println(now1); System.out.println(now2); } }package com.bbedu.date_; import java.util.Date; import java.time.Instant; public class Instant_ { public static void main(String[] args) { Instant now = Instant.now(); System.out.println(now); // from 方法 将 Instant 转为 Date 对象 Date date = Date.from(now); System.out.println(date); // toInstant 方法将 Date 转为 Instant Instant instant = date.toInstant(); System.out.println(instant); } }使用时查看 API 即可本章作业package com.bbedu.homework; import java.util.Arrays; public class Homework01 { public static void main(String[] args) { String str = "abcdef"; System.out.println(reverse(str, 2, 4)); } public static String reverse(String str, int start, int end){ if(! (str != null && start >= 0 && end > start && end < str.length())){ throw new RuntimeException("参数不正确"); } char[] chars = str.toCharArray(); char temp = ' '; while (start < end){ temp = chars[start]; chars[start] = chars[end]; chars[end] = temp; start++; end--; } return Arrays.toString(chars); } }package com.bbedu.homework; public class Homework02 { public static void main(String[] args) { String name = "Tom"; String pwd = "123456"; String email = "tom@qq.com"; try { userRegister(name, pwd, email); System.out.println("注册成功"); }catch (Exception e){ System.out.println(e.getMessage()); } } public static void userRegister(String name, String pwd, String email){ int nameLength = name.length(); if(!(nameLength >= 2 && nameLength <= 4)){ throw new RuntimeException("用户名长度在[2, 4]"); } if(!(pwd.length() == 6 && isDigital(pwd))){ throw new RuntimeException("密码长度为6,且全部为数字"); } int i = email.indexOf('@'); int j = email.indexOf('.'); if(!( i > 0 && j > i)){ throw new RuntimeException("邮箱有误"); } } public static boolean isDigital(String str){ char[] chars = str.toCharArray(); for (int i = 0; i < chars.length; i++) { if(chars[i] < '0' || chars[i] > '9'){ return false; } } return true; } }package com.bbedu.homework; import java.util.Arrays; public class Homework03 { public static void main(String[] args) { System.out.println(nameFormat("Chen xue Bin")); System.out.println(nameFormat("William jefferson Clinton")); } public static String nameFormat(String name){ if(name == null){ System.out.println("不能为空"); return null; } String[] s = name.split(" "); if(s.length != 3){ System.out.println("输入格式不正确"); return null; } // StringBuffer stringBuffer = new StringBuffer(); // stringBuffer.append(s[0]); // stringBuffer.append(","); // stringBuffer.append(s[2]); // stringBuffer.append(" ."); // stringBuffer.append(s[1].toUpperCase().charAt(0)); // return stringBuffer.toString(); String format = String.format("%s,%s .%c", s[2], s[0], s[1].toUpperCase().charAt(0)); return format; } }
2023年02月26日
68 阅读
0 评论
0 点赞
2023-02-26
Chapter12_异常
异常 (Exception)本章内容异常基本介绍如果程序员认为一段代码可能出现异常/问题,可以使用 try-catch 异常处理机制来解决,从而保证程序的健壮性将该代码块 -> 选中 -> crtl + alt + t 快捷键 -> 选中 try-catchJava语言中,将程序执行中的不正常情况成为“异常”。(开发过程中的语法和逻辑错误不是异常)执行过程中所发生的异常可以分为两大类:Error:Java虚拟机无法解决的严重问题。如 JVM 系统内部错误、资源耗尽等严重情况Exception:其他因编程错误或偶然的外在因素导致的一般性问题,可以 使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等。Exception 又分为两大类:运行时异常(程序运行时发生的异常)编译时异常(编程时,编译器检查出的异常)*异常体系图小结:运行时异常,是编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类以及它的子类都是运行时异常对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响编译时异常,是编译器要求必须处置的异常常见的运行时异常NullPointerException 空指针异常当应用程序试图再需要对象的地方使用 null 时,抛出该异常ArithmeticException 数学算数异常当出现异常的运算条件时,抛出此异常。例如“除以零”。ArrayIndexOutOfBoundsException 数组下标越界异常用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则为非法索引ClassCastException 类转换异常当试图将对象强制转换为不是实例的子类时,抛出该异常NumberFormatException 数字格式异常当应用程序试图将字符串转化成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常异常处理机制JVM 的处理方式:1. 输出异常信息 2. 退出程序如果程序员没有显式地处理异常,默认 throws细节如果 try 代码块有可能有多个异常,可以使用多个 catch 分别捕获不同的异常,相应处理要求子类异常写在前面,父类异常写在后面可以直接进行 try-finally 配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉。应用场景:执行一段代码,不管是否发生异常,都必须执行某个业务逻辑练习输出:4输出:4输出:i=43小结如果没有出现异常,则执行 try 中的所有语句,不执行 catch 块中语句,如果有 finally,最后还需要执行 finally 里面的语句如果出现异常,则 try 块中异常发生后,try 块剩下的语句不再执行。将执行 catch 块中的语句,如果有 finally,最后还需要执行 finally 里面的语句throws处理机制如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。细节对于编译异常,程序必须处理对于运行时异常,程序中如果没有处理,默认就是 throws 的方式处理子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出异常类型的子类型throws 和 try-catch 二选一自定义异常package com.bbedu.exception_; public class CustomException { public static void main(String[] args) { int age = 180; if (!(age >= 18 && age <= 120)){ throw new AgeException("年龄需要在 18-120 之间"); } System.out.println("正确"); } } class AgeException extends RuntimeException { public AgeException(String message) { super(message); } }一般情况下,我们自定义异常是继承 RuntimException,因为有默认的异常处理机制,比较方便throw 和 throws 的区别
2023年02月26日
41 阅读
0 评论
0 点赞
2023-02-26
Chapter11_枚举和注解
枚举和注解本章内容枚举(enumeration, 简写enum)枚举是一组常量的集合,属于一种特殊的类,里面只包含一组有限的特定的对象实现方式:自定义枚举类型package com.bbchen.enum_; public class Enumeration02 { public static void main(String[] args) { System.out.println(Season.SPRING); System.out.println(Season.SUMMER); System.out.println(Season.AUTUMN); System.out.println(Season.WINTER); } } // 演示自定义枚举实现 class Season { private String name; private String desc; public final static Season SPRING = new Season("春天", "温暖"); public final static Season SUMMER = new Season("夏天", "炎热"); public final static Season AUTUMN = new Season("秋天", "凉爽"); public final static Season WINTER = new Season("冬天", "寒冷"); // 1.构造器私有化,防止直接 new // 2.去掉 setter 方法,防止属性被修改 // 3.在 Season 内部,直接创建固定的对象 // 4.final static private Season(String name, String desc) { this.name = name; this.desc = desc; } public String getName() { return name; } public String getDesc() { return desc; } @Override public String toString() { return "Season{" + "name='" + name + '\'' + ", desc='" + desc + '\'' + '}'; } }使用 enum关键字 来实现package com.bbchen.enum_; public class Enumeration03 { public static void main(String[] args) { System.out.println(Season2.SPRING); System.out.println(Season2.SUMMER); System.out.println(Season2.AUTUMN); System.out.println(Season2.WINTER); } } // 演示 enum关键字 枚举实现 enum Season2 { // public final static Season2 SPRING = new Season2("春天", "温暖"); // public final static Season2 SUMMER = new Season2("夏天", "炎热"); // public final static Season2 AUTUMN = new Season2("秋天", "凉爽"); // public final static Season2 WINTER = new Season2("冬天", "寒冷"); // 如果使用 enum 来实现枚举类 // 1.使用 enum 替代 class // 2.使用 SPRING("春天", "温暖"); 代替 // public final static Season2 SPRING = new Season2("春天", "温暖"); // 3.如果有多个对象常量,使用 ,号间隔即可 // 4.要求将定义常量写在前面 SPRING("春天", "温暖"), SUMMER("夏天","炎热"), AUTUMN("秋天", "凉爽"), WINTER("冬天", "寒冷"); private String name; private String desc; private Season2(String name, String desc) { this.name = name; this.desc = desc; } public String getName() { return name; } public String getDesc() { return desc; } @Override public String toString() { return "Season{" + "name='" + name + '\'' + ", desc='" + desc + '\'' + '}'; } }注意事项当我们使用 enum关键字 来开发一个枚举类时,默认会继承 Enum 类,而且是一个 final 类,使用 javap 来证明使用 SPRING("春天", "温暖"); 代替 public final static Season2 SPRING = new Season2("春天", "温暖");无参构造器创建常量对象,则省略可以不写括号()当有多个枚举对象是,使用逗号间隔,最后一个以分号结尾枚举对象必须放在枚举类的最前面练习Enum 成员方法package com.bbchen.enum_; /** * 演示 Enum 类的各种方法,使用 Season2 演示 */ public class EnumMethod { public static void main(String[] args) { Season2 autumn = Season2.AUTUMN; // name() 输出枚举对象的名字 System.out.println(autumn.name()); // ordinal() 输出该枚举对象的次序/编号,从0开始 System.out.println(autumn.ordinal()); // values() 返回 Season2[], 含有定义的所有枚举 Season2[] values = Season2.values(); for (Season2 season: values) { System.out.println(season); } // valueOf() 将字符串转换成枚举对象,要求字符串必须为已有常量名 // 1.根据输入的 "AUTUMN" 到 Season2 的枚举对象去查找 // 2.如果找到,就返回该对象,如果没有则报错 System.out.println("autumn1 = " + Season2.valueOf("AUTUMN")); // compareTo() 将枚举对象的编号进行比较 // self.ordinal - other.ordinal // 调用元素编号 - 比较元素编号 System.out.println(Season2.AUTUMN.compareTo(Season2.SPRING)); } } 练习package com.bbchen.enum_; public class EnumExercise02 { public static void main(String[] args) { Week[] weeks = Week.values(); System.out.println("===所有星期的信息如下==="); for (Week week: weeks) { System.out.println(week); } } } enum Week { MONDAY("星期一"), TUESDAY("星期二"), WEDNESDAY("星期三"), THURSDAY("星期四"), FRIDAY("星期五"), SATURDAY("星期六"), SUNDAY("星期日"); private final String name; Week(String name) { this.name = name; } @Override public String toString() { return name; } }enum 实现接口使用 enum 关键字后,就不能在继承其他类了,因为 enum 会隐式继承 Enum,而 Java 是单继承制enum 实现的枚举类,仍然是一个类,所以还是可以实现接口的注解 (Annotation,了解即可)注解(Annotation)也被称为元数据(Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息。和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。在 JavaSE 中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替 javaEE 旧版中所遗留的繁冗代码和 XML 配置等。Annotation三个基本的 Annotation:@Override: 限定某个方法,是重写父类方法,该注解只能用于方法@Deprecated: 用于表示某个程序元素(类,方法等)已经过时,即不再推荐使用,但是仍然可以使用@SuppressWarnings: 抑制编译器警告元注解
2023年02月26日
33 阅读
0 评论
0 点赞
2023-02-26
Chapter10_OOP高级
面向对象编程(高级)本章内容类变量引入package com.bbedu.static_; public class ChildGame { public static void main(String[] args) { // 定义一个count int count = 0; Child ming = new Child("ming"); ming.join(); count++; Child qiang = new Child("qiang"); qiang.join(); count++; Child li = new Child("li"); li.join(); count++; System.out.println("共有" + count + "个人加入游戏"); } } class Child { private String name; public Child(String name) { this.name = name; } public void join() { System.out.println(name + " 加入了游戏..."); } }分析:count 是一个独立于对象,很尴尬以后我们访问 count 很麻烦, 没有使用到 OOP因此,我们引出 类变量/静态变量快速入门package com.bbedu.static_; public class ChildGame { public static void main(String[] args) { Child ming = new Child("ming"); ming.join(); Child qiang = new Child("qiang"); qiang.join(); Child li = new Child("li"); li.join(); // 类变量可以通过类名直接访问 System.out.println("共有" + Child.count + "个人加入游戏"); } } class Child { private String name; // 类变量,又叫静态变量 // 该变量最大的特点是会被所有的 Child 对象实例共享 public static int count = 0; public Child(String name) { this.name = name; } public void join() { System.out.println(name + " 加入了游戏..."); count++; } }理解静态变量被对象共享,在类加载中就生成了,JDK7以上版本,静态域存储于定义类型的 Class 对象中,Class 对象如同堆中其他对象一样,存在于 GC 堆中。因此不影响对静态变量的使用类变量又叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的独享去访问它,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的都是同一个变量定义类变量:访问修饰符 static 数据类型 变量名; [推荐]static 访问修饰符 数据类型 变量名;访问类变量:类名.类变量 [推荐]或者对象名.类变量细节什么时候使用类变量当我们需要让某个类的所有对象共享一个变量时,就可以考虑使用类变量类变量与实例变量(普通属性)的区别类变量是该类的所有对象共享的,而实例变量是每个对象独享的加上 static 称为类变量或静态变量,否则称为实例变量/普通变量/非静态变量类变量可以通过 类名.类变量名 或者 对象名.类变量名 来访问,但 java 设计者推荐使用 类名.类变量名 的方式来访问实例变量不能通过 类名.变量名 的方式来访问类变量是在类创建时就初始化了,也就是说,即使没有创建对象,只要类加载了,就可以使用类变量了类变量的生命周期是随着类的加载开始,随着类的消亡而销毁类方法基本介绍类方法也叫静态方法,形式如下:访问修饰符 static 返回数据类型 方法名(){ } [推荐]static 访问修饰符 返回数据类型 方法名(){ }类方法的调用:类名.类方法名 或 对象名.类方法名 (需要满足访问修饰符的访问权限和范围)类方法的使用场景:当方法中不涉及到任何和对象相关的成员,则可以讲方法设计成静态方法,提高开发效率如果我们希望不创建对象,也可以调用某个方法(即当作工具来使用),这时,把方法设计成静态方法非常合适比如,工具类中的方法 utils Math类、Arrays类、Collections集合类细节类方法和普通方法都是随着类的加载而加载,讲结构信息存储在方法区类方法可以通过类名调用,也可以通过对象名调用普通方法和对象有关,需要通过对象名调用,比如 对象名.方法(参数),不能通过类名调用类方法中不允许使用和对象有关的关键字,如 super 和 this,普通方法可以类方法中只能访问 静态变量 或 静态方法(静态方法只能访问静态成员)普通成员方法,既可以访问 非静态方法/普通变量(方法),也可以访问 静态方法/静态变量(方法)练习count=9count=1011id++; 错误输出:014main 方法理解 main 方法public static void main(String[] args){}main 方法是虚拟机调用java 虚拟机需要调用类的 main() 方法,所以该方法的访问权限必须是 publicjava 虚拟机在执行 main() 方法时,不必创建对象,所以方法必须是 static该方法接收 String 类型的数组参数,该数组中保存执行 java 命令时传递给所运行的类的参数java 执行的程序 参数1 参数2 参数3特别说明在 main() 方法中,我们可以直接调用 main 方法所在类的静态方法或静态属性但是,不能直接访问该类中的非静态成员,必须创建该类的有个实例对象后,才能通过这个对象去访问类中的非静态成员package com.bbedu.main_; public class Main01 { // 静态的属性 private static String name = "秋高气爽"; public static void hi(){ System.out.println("Main01 的 hi 方法"); } // 非静态成员 private int n1 = 10000; public void ok(){ System.out.println("Main01 的 ok 方法"); } public static void main(String[] args) { // 可以直接使用 name // 静态方法可以直接访问本类的静态成员 System.out.println("name=" + name); hi(); // 静态方法main不可以访问非静态成员 //System.out.println("n1=" + n1); // 错误 Main01 main01 = new Main01(); System.out.println("n1=" + main01.n1); main01.ok(); } }idea 中传值代码块代码化块又称为初始化块,属于类中的成员[即是类的一部分],类似于方法,将逻辑语句封装在方法体中,通过包围起来。但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用。基本语法[修饰符]{ 代码}修饰符可选,要写的话,也只能写 static代码块分为两类,使用 static 修饰的叫静态代码块,没有 static 修饰的,叫普通代码块逻辑语句可以为任意逻辑语句(输入、输出、方法调用、循环、判断等); 号可以写,也可以忽略细节static 代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,就执行类声明时候被加载(1) 创建对象实例时 (new) (2) 创建子类对象实例,父类也会被加载 (3) 使用类的静态成员时 (静态属性、静态方法)普通的代码块,在创建对象实例是,会被隐式地调用。被创建一次,就会调用一次。如果只是使用类的静态成员,普通代码块并不会执行。可以把普通代码块简单的理解为构造器的补充创建一个对象时,在一个类中调用顺序是:调用静态代码块和静态属性初始化(若有多个静态代码块和多个静态变量初始化,则按顺序依次调用)调用普通代码块和普通属性的初始化(同上,若有多个,则按顺序)调用构造器构造方法(构造器) 的最前面隐含了 super() 和 调用普通代码块,静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于构造器和普通代码块执行的创建子类对象时(继承关系),同名的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:/面试题父类的静态代码块和静态属性(优先级一样,按定义顺序执行)子类的静态代码块和静态属性(优先级一样,按定义顺序执行)父类的普通代码块和普通属性初始化(优先级一样。按定义顺序执行)父类的构造方法子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)子类的构造方法总结:父子静,父普构,子普构静态代码块只能调用静态成员,普通代码块可以调用所有成员练习输出:in static block!total = 100total = 100输出:静态成员sam初始化static块执行sam1成员初始化Test默认构造函数被调用单例设计模式什么是设计模式静态方法和属性的经典使用设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格以及解决问题的思考方式。设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己在思考和摸索什么是单例模式所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法单例模式有两种方式:饿汉式,懒汉式饿汉式构造器私有化 => 防止直接 new类的内部创建对象向外暴露一个静态的公共方法package com.bbedu.single_; public class SingleTon01 { public static void main(String[] args) { GirlFriend instance = GirlFriend.getInstance(); System.out.println(instance); GirlFriend instance1 = GirlFriend.getInstance(); System.out.println(instance1); System.out.println(instance == instance1); } } class GirlFriend { private String name; // 静态方法只能访问静态成员,因此 gf 需要为静态 private static GirlFriend gf = new GirlFriend("Mary"); // 保证我们只能创建一个 GirlFriend 对象 //1. 构造器私有化 => 防止直接 new //2. 类的内部创建对象 //3. 向外暴露一个静态的公共方法 private GirlFriend(String name){ this.name = name; } public static GirlFriend getInstance(){ return gf; } @Override public String toString() { return "GirlFriend{" + "name='" + name + '\'' + '}'; } } 懒汉式构造器私有化 => 防止直接 new类的内部创建对象向外暴露一个静态的公共方法只有当用户调用 getInstance 方法时,才创建对象实例package com.bbedu.single_; /** * 演示懒汉式的单例模式 */ public class SingleTon02 { public static void main(String[] args) { System.out.println(Cat.n1); Cat instance = Cat.getInstance(); System.out.println(instance); } } // 希望只能创建一个 Cat 对象 class Cat { public static int n1 = 888; private String name; private static Cat cat; private Cat(String name) { System.out.println("构造器被调用..."); this.name = name; } public static Cat getInstance(){ if (cat == null){ cat = new Cat("小花"); } return cat; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + '}'; } }区别:饿汉式 VS 懒汉式二者最主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建。饿汉式不存在线程安全问题,懒汉式存在线程安全问题。(后面学习线程后,会完善)3. 饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题。4. 在我们javaSE标准类中,java.lang.Runtime就是经典的单例模式。final 关键字final 可以修饰类、属性、方法和局部变量在某些情况下,程序员可能有以下需求,就会用到 final:当不希望类被继承时当不希望父类的某个方法被子类重写时当不希望类的某个属性的值被修改时当不希望某个局部变量被修改时细节final 修饰的属性又叫常量,一般用 XX_XX_XX来命名final 修饰的属性在定义时,必须赋初值,并且以后不能在修改,赋值可以在下面位置之一:定义时构造器中代码块中如果 final 修饰的属性是静态的,贼初始化的位置只能是:定义时在静态代码块,不能再构造器中赋值final 类不能继承,但是可以实例化对象如果类不是 final 类,但是含有 final 方法,则该方法虽然不能重写,但是可以被继承,即仍然遵守继承规则一般来说,如果一个类已经是 final 类了,就没必要再将方法修饰成 final 方法final 不能修饰构造方法final 和 static 往往搭配使用,效率更高,不会导致类的加载,底层编译器做了相关优化包装类(Integer,String,Double)是 final 类,不能被继承注意final 关键字只是表示存储在变量中的对象不会再指示另一个不同的对象,不过这个对象可以更改,例如:final char[] a = {'a', 'b', 'c'}; a[0] = 'd'; System.out.println(a);换句话说,final 修饰基本数据类型的话值是不能进行改变的,修饰引用类型的话就是指地址不能被改变而值可以进行修改,这个需要区分一下练习package com.bbedu.final_; public class FinalExercise01 { public static void main(String[] args) { Circle circle = new Circle(5); System.out.println(circle.area()); } } class Circle { private double radius; private final double PI_1 = 3.14; private final double PI_2; private final double PI_3; { PI_2 = 3.14; } public Circle(double radius){ this.radius = radius; PI_3 = 3.14; } public double area(){ return PI_1 * radius * radius; } }有误,x不可自增抽象类当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类所谓抽象方法,就是没有实现的方法 => 没有方法体当一个类中存在抽象方法时,需要将该类声明为 abstract 类一般来说,抽象类会被继承,由其子类来实现抽象方法介绍用abstract关键字来修饰一个类时,这个类就叫抽象类访问修饰符abstract类名{}用abstract关键字来修饰一个方法时,这个方法就是抽象方法访问修饰符 abstract 返回类型方法名(参数列表);//没有方法体抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类()抽象类,是考官比较爱问的知识点,在框架和设计模式使用较多细节抽象类不能实例化抽象类不一定要包含 abstract 方法一旦包含了 abstract 方法,则这个类必须声明为 abstractabstract 只能修饰类和方法,不能修饰属性和其他抽象类可以拥有任意成员(抽象类本质还是类),如:非抽象方法、构造方法、静态属性...抽象方法不能有主体,即不能实现如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为 abstract 类抽象方法不能使用 private final static 来修饰,因为这些关键字都是和重写违背的练习package com.bbedu.abstract_; abstract public class Employee { private String name; private int age; private double sal; public Employee(String name, int age, double sal) { this.name = name; this.age = age; this.sal = sal; } // 将 work 做成一个抽象方法 abstract public void work(); 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 double getSal() { return sal; } public void setSal(double sal) { this.sal = sal; } }package com.bbedu.abstract_; public class Manager extends Employee{ private double bonus; public Manager(String name, int age, double sal, double bonus) { super(name, age, sal); this.bonus = bonus; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } @Override public void work() { System.out.println("经理" + getName() + "工作中..."); } }package com.bbedu.abstract_; public class CommonEmployee extends Employee{ public CommonEmployee(String name, int age, double sal) { super(name, age, sal); } @Override public void work() { System.out.println("普通员工" + getName() + "工作中..."); } }package com.bbedu.abstract_; public class AbstractExercise01 { public static void main(String[] args) { Manager tim = new Manager("Tim", 32, 600000, 5000); tim.work(); CommonEmployee rick = new CommonEmployee("Rick", 40, 50000); rick.work(); } }抽象类最佳实践-模板设计模式需求有多个类,完成不同的任务能够统计得到各自完成任务的时间package com.bbedu.abstract_; /** * 模板设计模式 */ abstract public class Template { public abstract void job(); public void calculateTime(){ long start = System.currentTimeMillis(); job(); long end = System.currentTimeMillis(); System.out.println("执行时间:" + (end - start)); } }package com.bbedu.abstract_; public class AA extends Template{ // 实现Template的抽象方法 public void job(){ long num = 0; for (long i = 1; i <= 1000000000; i++) { num += i; } System.out.println(num); } }package com.bbedu.abstract_; public class BB extends Template{ public void job(){ long num = 0; for (long i = 1; i <= 80000; i++) { num *= i; } System.out.println(num); } }package com.bbedu.abstract_; public class TestTemplate { public static void main(String[] args) { AA aa = new AA(); aa.calculateTime(); BB bb = new BB(); bb.calculateTime(); } }接口基本介绍就看就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来。语法:interface 接口名{ // 属性 // 方法}class 类名 implements 接口 { 自己属性; 自己方法; 必须实现的接口的抽象方法;}在接口中,抽象方法可以省略 abstract 关键字在jdk8后,可以有默认实现方法,需要使用 default 关键字修饰;可以有静态方法细节接口不能被实例化接口中的所有方法都是 public 方法,接口中的抽象方法,可以不用 abstract 修饰一个普通类实现接口,就必须将该接口的所有方法都实现抽象类实现接口,可以不用实现接口的方法一个类可以同时实现多个接口接口中的属性,只能是 final 的,而且是 public static final 修饰符,比如 int a = 1; 实际上等价于 public static final int a = 1;(必须初始化)接口中属性的访问形式:接口名.属性名接口不能继承其他的类,但是可以继承多个别的接口练习都正确,输出:232323实现接口 vs 继承类当子类继承了父类,就自动的拥有了父类的功能,如果子类需要扩展功能,可以通过实现接口的方式来扩展可以理解:实现接口是对 java 单继承的一种补充接口和继承解决的问题不同继承的价值主要在于:解决代码的复用性和可维护性接口的价值主要在于:设计,设计好各种规范(方法),让其他类去实现这些方法,更加灵活继承是满足 is-a 的关系,而接口只需满足 like - a的关系接口在一定程度上实现代码解耦(即 接口规范性+动态绑定)接口的多态特性多态参数,接口类型的变量 可以指向 实现了此接口的对象实例 => 类比继承的向上转型多态数组,动态绑定 + 使用 instanceof 判断 + 向下转型多态传递,接口间继承,类实现时遵守继承规则练习pX() 中 x 不明确,A.x, super.x,输出为:01小结类的五大成员:属性方法构造器代码块*内部类内部类一个类的内部又完整地嵌套了另一个类结构,被嵌套的类成为内部类(inner class),嵌套其他类的类成为外部类(outer class)。内部类是java 类的第五大成员,内部类的最大特点是可以直接访问私有属性,并且可以体现类鱼类的包含关系。内部类是学习的重难点,底层源码中有大量的内部类基本语法class Outer{ // 外部类 class Inner{ // 内部类 }}class Other{ // 外部其他类}分类定义在外部类局部位置上:局部内部类(有类名)匿名内部类(没有类名,重点)定义在外部类的成员位置上:成员内部类(没用 static 修饰)静态内部类(使用 static 修饰)局部内部类局部内部类是定义在外部类的局部位置,通常在方法可以直接访问外部类的所有成员,包含私有的不能添加访问修饰符,但是可以使用 final 修饰作用域:仅仅在定义它的方法或代码块中局部内部类可以直接访问外部类的成员外部类在方法中,可以创建 Inner02 对象,然后调用方法即可如果外部类和局部内部类的成员重名时,默认就近原则,如果想访问外部类的成员,使用 外部类名.this.成员 去访问package com.bbedu.innerclass; /** * 演示局部内部类的使用 */ public class LocalInnerClass { public static void main(String[] args) { Outer02 outer02 = new Outer02(); outer02.m1(); System.out.println("Outer02 hashcode=" + outer02); } } class Outer02 { private int n1 = 100; private void m2() { System.out.println("Outer02 m2()"); } public void m1() { // 1.局部内部类是定义在外部类的局部位置,通常在方法 // 3.不能添加访问修饰符,但是可以使用 final 修饰 // 4.作用域:仅仅在定义它的方法或代码块中 class Inner02 { // 本质还是一个类 private int n1 = 999; public void f1() { // 2.可以直接访问外部类的所有成员,包含私有的 // 5.局部内部类可以直接访问外部类的成员,如下面的 n1 和 m2() System.out.println("n1=" + n1 + " 外部类的n1=" + Outer02.this.n1); System.out.println("Outer02.this hashcode=" + Outer02.this); m2(); } } class Inner03 extends Inner02 { } // 6.外部类在方法中,可以创建 Inner02 对象,如何调用方法即可 Inner02 inner02 = new Inner02(); inner02.f1(); } }匿名内部类(非常重要)本质是类内部类该类没有名字同时是一个对象基本语法new 类或接口(参数列表){ 类体;}细节匿名内部类的语法比较奇特。匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特性,也有创建对象的特征,因此可以调用匿名内部类方法可以直接访问外部类的所有成员,包含私有的不能添加访问修饰符,因为它的地位就是一个局部变量作用域:仅仅在定义它的方法或代码块中外部其他类不能访问匿名内部类外部类和匿名内部类的成员重名时,匿名内部类访问时,默认就近原则,如果想访问外部类的成员,使用 外部类名.this.成员 去访问package com.bbedu.innerclass; /** * 演示匿名内部类的使用 */ public class AnonymousInnerClassDetail { public static void main(String[] args) { Outer05 outer05 = new Outer05(); outer05.f1(); // 外部其他类不能访问匿名内部类 } } class Outer05 { private int n1 = 99; public void f1(){ // 创建一个基于类的匿名内部类 Person p = new Person(){ private int n1 = 66; @Override public void hi() { System.out.println("匿名内部类重写了 hi()"); System.out.println("n1 = " + n1 + "\nOuter05 n1 = " + Outer05.this.n1); } }; p.hi(); // 真实的运行类型为 Outer$1 // 第二种调用,直接调用匿名对象的 hi() 方法 // new Person(){ // @Override // public void hi() { // System.out.println("匿名内部类重写了 hi() 哈哈哈"); // } // // @Override // public void ok(String str) { // super.ok(str); // } // }.ok("Mary"); } } class Person { public void hi() { System.out.println("Person hi()"); } public void ok(String str){ System.out.println("Person ok() " + str); } } // 抽象类、接口...最佳实践当作实参直接传递,简洁高效package com.bbedu.innerclass; public class InnerClassExercise01 { public static void main(String[] args) { f1(new AA(){ @Override public void show() { System.out.println("这是一幅画"); } }); // 传统方法 f1(new Pic()); } // 静态方法 public static void f1(AA aa){ aa.show(); } } interface AA { void show(); } class Pic implements AA{ // 类实现AA -> 硬编码 @Override public void show() { System.out.println("这是一幅画"); } }package com.bbedu.innerclass; public class InnerClassExercise02 { public static void main(String[] args) { CellPhone cellPhone = new CellPhone(); // 传递的是实现了 Bell 接口的匿名内部类 cellPhone.alarmClock(new Bell() { @Override public void ring() { System.out.println("懒猪起床了!!"); } }); // 相当于: Bell bell = new Bell(){ @Override public void ring() { System.out.println("懒猪起床了!!"); } }; cellPhone.alarmClock(bell); cellPhone.alarmClock(new Bell() { @Override public void ring() { System.out.println("小伙伴上课了"); } }); } } interface Bell{ void ring(); } class CellPhone{ public void alarmClock(Bell bell){ bell.ring(); } }成员内部类定义在外部类的成员位置可以添加任意访问修饰符,因为它的地位就是一个成员作用域是整个外部类类体可以直接访问外部类成员要使用成员内部类,在外部类创建其实例,然后使用相关的方法外部其他类访问成员内部类:两种方法,详见代码重名遵守就近原则,如果想访问外部类的成员,使用 外部类名.this.成员 去访问package com.bbedu.innerclass; public class MemberInnerClass01 { public static void main(String[] args) { Outer08 outer08 = new Outer08(); outer08.t1(); // 外部其他类,使用衬衣内部类的两种方式 // 1、相当于把 new Inner08() 当作是 outer08 的成员,不必纠结 Outer08.Inner08 inner08 = outer08.new Inner08(); inner08.say(); // 2.在外部类中编写一个方法,可以返回 Inner08 的一个对象实例 Outer08.Inner08 inner081 = outer08.getInner08Instance(); inner081.say(); // 3.把new 外部类 和 方法1 合起来 } } class Outer08{ private int n1 = 100; public String name = "张三"; class Inner08 { // 成员内部类 private int sal = 999; private int n1 = 66; public void say(){ // 可以访问外部类的所有成员 System.out.println("n1 = " + n1 + " name = " + name + " Outer08 n1 = " + Outer08.this.n1); } } public Inner08 getInner08Instance(){ return new Inner08(); } public void t1(){ Inner08 inner08 = new Inner08(); inner08.say(); System.out.println(inner08.sal); } }静态内部类在成员内部类的基础上,加上 static 修饰可以直接访问外部类的所有静态成员,包括私有的可以添加任意修饰符作用域:同其他的成员,为整个类体外部其他类访问静态内部类,见代码重名遵守就近原则,如果想访问外部类的成员,使用 外部类名.成员 去访问package com.bbedu.innerclass; public class StaticInnerClass01 { public static void main(String[] args) { Outer10 outer10 = new Outer10(); outer10.m10(); // 外部其他类访问静态内部类 // 方式1,直接通过类名访问 Outer10.Inner10 inner10 = new Outer10.Inner10(); inner10.say(); // 方式2,编写一个方法,返回静态内部类的对象实例 Outer10.Inner10 inner101 = outer10.getInner10(); inner101.say(); Outer10.Inner10 inner102 = Outer10.getInner10_(); inner102.say(); } } class Outer10 { public static String name = "张三"; private static void cry(){ System.out.println("Outer10 cry()"); } static class Inner10 { // 成员内部类 private String name = "Mary"; public void say() { // 可以访问外部类的所有静态成员 System.out.println(name); System.out.println(Outer10.name); cry(); } } public void m10(){ Inner10 inner10 = new Inner10(); inner10.say(); } public Inner10 getInner10(){ return new Inner10(); } public static Inner10 getInner10_(){ return new Inner10(); } }练习5 5总结面向对象(基础、中级、高级)到此结束~?我亦无他,惟手熟尔本章练习结果:注意 color 是静态变量9.0 red100.0 redpackage homework; public class Homework02 { public static void main(String[] args) { Frock frock = new Frock(); System.out.println(frock.getNextNum()); System.out.println(frock.getNextNum()); Frock frock1 = new Frock(); Frock frock2 = new Frock(); Frock frock3 = new Frock(); System.out.println(frock1.getSerialNumber()); System.out.println(frock2.getSerialNumber()); System.out.println(frock3.getSerialNumber()); } } class Frock { private static int currentNum = 100000; private int serialNumber; public int getNextNum(){ currentNum += 100; return currentNum; } public Frock() { serialNumber = getNextNum(); } public int getSerialNumber() { return serialNumber; } }package homework; public class Homework03 { public static void main(String[] args) { Animal cat = new Cat(); cat.shout(); Animal dog = new Dog(); dog.shout(); } } abstract class Animal { abstract void shout(); } class Cat extends Animal { @Override void shout() { System.out.println("猫会喵喵叫~"); } } class Dog extends Animal { @Override void shout() { System.out.println("狗会汪汪叫~"); } }package homework; public class Homework04 { public static void main(String[] args) { Cellphone cellphone = new Cellphone(); cellphone.testWork(new Cal() { @Override public double work(double n1, double n2) { return n1 + n2; } }, 10, 20); } } interface Cal { double work(double n1, double n2); } class Cellphone{ public void testWork(Cal iCal, double n1, double n2){ double work = iCal.work(n1, n2); System.out.println("result = " + work); } }package homework; public class Homework05 { public static void main(String[] args) { new A().test(); } } class A { private String name = "Bob"; public void test(){ class B{ private String name = "Tom"; public void show(){ System.out.println("Inner B class name=" + name + "\nA class name=" + A.this.name); } } B b = new B(); b.show(); } }领略程序结构:package homework; import javax.print.attribute.standard.JobHoldUntil; public class Homework06 { public static void main(String[] args) { Person monk = new Person("唐僧", new Boat()); monk.common(); monk.passRiver(); monk.passRiver(); monk.common(); monk.passFireHill(); } } interface Vehicles { void work(); } class Horse implements Vehicles { @Override public void work() { System.out.println("骑马中..."); } } class Boat implements Vehicles { @Override public void work() { System.out.println("开船中..."); } } class Plane implements Vehicles { @Override public void work() { System.out.println("开飞机..."); } } class TransportFactory { private static Horse horse = new Horse(); public static Boat getBoat() { Boat boat = new Boat(); return boat; } // 确保马始终是同一匹,饿汉式 public static Horse getHorse() { return horse; } public static Plane getPlane() { Plane plane = new Plane(); return plane; } } class Person { private String name; private Vehicles vehicles; public Person(String name, Vehicles vehicles) { this.name = name; this.vehicles = vehicles; } // 把具体的要求封装成方法 => 编程思想 public void passRiver(){ //先得到船 if(!(vehicles instanceof Boat)){ vehicles = TransportFactory.getBoat(); } vehicles.work(); } public void common() { // 判断一下当前的 vehicles 属性是否已经存在 if(!(vehicles instanceof Horse)){ vehicles = TransportFactory.getHorse(); // 向上转型 } vehicles.work(); } public void passFireHill(){ if(!(vehicles instanceof Plane)){ vehicles = TransportFactory.getPlane(); } vehicles.work(); } } package homework; public class Homework07 { public static void main(String[] args) { Car car = new Car(50.4); car.new Air().flow(); Car car1 = new Car(-10.0); car1.new Air().flow(); Car car2 = new Car(24); car2.new Air().flow(); } } class Car { private double temperature; public Car(double temperature) { this.temperature = temperature; } class Air { public void flow() { if (temperature > 40) { System.out.println("吹冷气"); } else if (temperature < 0) { System.out.println("吹暖气"); } else { System.out.println("关闭空调"); } } } }package homework; public class Homework08 { public static void main(String[] args) { // 演示 switch 使用 Color green = Color.GREEN; green.show(); switch (green) { case GREEN: System.out.println("匹配到绿色"); break; case RED: System.out.println("匹配到红色"); break; case BLUE: System.out.println("匹配到蓝色"); break; default: System.out.println("没有匹配到"); } } } interface IColor { void show(); } enum Color implements IColor{ RED(255,0,0), BLUE(0, 0,255), BLACK(0,0,0), YELLOW(255,255,0), GREEN(0,255,0); private int redValue; private int greenValue; private int blueValue; Color(int redValue, int greenValue, int blueValue) { this.redValue = redValue; this.greenValue = greenValue; this.blueValue = blueValue; } @Override public void show() { System.out.println("属性值为" + redValue + " " + greenValue + " " + blueValue); } }
2023年02月26日
47 阅读
0 评论
0 点赞
2023-02-26
Chapter09_房屋出租系统
源码见附件需求设计程序框架图(分层模式 => 当软件比较复杂,需要模式管理)系统又那些类(文件)明确类与类的调用关系HouseView.java [界面] 显示界面;接收用户的输入;调用 HouseService 类完成对房屋信息的各种操作HouseService.java [业务层] 响应 HouseView 的调用;完成对服务信息的各种操作(增删改查 C[create]R[read]U[update]D[delete])House.java [domain/model] 一个 House 对象表示一个房屋信息HouseRentApp.java [程序入口] 调用 HouseVies对象,调用该对象,显示主菜单Utility [工具类] 完成获取用户的各种输入实现准备工具类在实际开发中,公司会提供响应的工具类和开发库,可以提高开发效率,程序员也需要能够看懂别人写的代码,并且能够正确地调用菜单实现功能的三部曲:明确完成功能 -> 思路分析 -> 代码实现用户打开软件,可以看到主菜单,可以退出软件思路:在 HouseView.java 中,编写一个 mainMenu,显示菜单出租列表各司其职功能实现
2023年02月26日
57 阅读
0 评论
0 点赞
1
...
5
6
7
...
11