• 深入理解面向对象(第二篇)


    目录

    🏀面向对象

    🥅package和import

    🥅访问控制权限修饰符

    🥅Object类

    🥅匿名内部类


    🏀面向对象

    🥅package和import

    ❤️package

    1、为什么要使用package?

        package是java中包机制,包机制的作用是为了方便程序的管理;

        不同功能的类分别存放在不同的包下(按照功能划分的,不同软件包具有不同的功能)

    2、package是怎么用的?

        package是一个关键字,后面加包名;例如:package com.dlu.javase.day01

        注意:package语句只允许出现在java源代码的第一行

    3、包名的命名规范?

        一般采用公司域名倒叙的方式(因为公司域名具有全球唯一性)

        包名命名规范:公司域名倒序+/名+模块名+功能名

    4、对于带有package的java程序怎么编译?怎么运行?

       ⭐️以文本编译器为例:

       1、编译javac -d . PackageTest01

           -d表示带包编译

           .表示编译之后生成的class文件放到当前目录下

       2、运行java com.dlu.javase.day01.PackageTest01

       3、解释:实际上在PackageTest01.java文件目录下会生成com文件夹---》com文件夹下生成dlu文件夹---》dlu文件夹下生成javase文件夹---》javase文件夹下生成day01文件夹---》day01文件夹下生成PackageTest01.class文件。运行时还是在PackageTest01.java文件目录下执行:java com.dlu.javase.day01.PackageTest01即可!

      ⭐️IDEA编译器为例:

        1、先创建包(Package);和创建类的时候步骤一致

        2、创建包之后,在包下面再创建类,生成的类就会自动带上package com.dlu.javase.day01;然后直接运行就行

    1. package com.dlu.javase.day01;
    2. public class PackageTest01 {
    3. public static void main(String[] args) {
    4. System.out.println("HelloWorld");
    5. }
    6. }

    ❤️import

    ⭐例1:两个类包名相同(包名能省略)

    1. package com.dlu.javase.day01; //包名与PackageTest01包名相同
    2. public class Test01{
    3. public static void main(String[] args){
    4. // 创建PackageTest01对象
    5. //PackageTest01的完整类名是:com.dlu.javase.day01.PackageTest01(这是带包的情况下类名)
    6. com.dlu.javase.day01.PackageTest01 hw = new com.dlu.javase.day01.PackageTest01();
    7. System.out.println(hw);//com.dlu.javase.day01.PackageTest01@15db9742
    8. //包名省略?---也没问题
    9. //这里的包名之所以可以省略,是因为PackageTest01和Test01在同一个Package(包)下
    10. PackageTest01 hw1 = new PackageTest01();
    11. System.out.println(hw1);//com.dlu.javase.day01.PackageTest01@6d06d69c
    12. }
    13. }

    ⭐例2:两个类包名不同(包名不能省略,可以用import进行导包)

    1、import什么时候使用?例如:A类中使用B类:
            A和B类都在同一个包下;不需要import!
            A和B类不在同一个包下;需要使用import!

           默认java.lang.*;这个包下的类(直接子类)都不需要使用import导入     

    2、import怎么用?
            import语句只能出现在package语句下,class声明语句之前。
            import语句也可以采用星号(*)的方式,星号省略的是当前类名,不能多省略

    1. package com; //包名与PackageTest01包名不相同
    2. //import com.dlu.javase.day01.PackageTest01;//导如需要的包
    3. import com.dlu.javase.day01.*;//采用星号的方式也是可以的
    4. public class Test02{
    5. public static void main(String[] args){
    6. // 创建PackageTest01对象
    7. com.dlu.javase.day01.PackageTest01 hw = new com.dlu.javase.day01.PackageTest01();
    8. System.out.println(hw);//com.dlu.javase.day01.PackageTest01@15db9742
    9. //这里包名就不能省略:
    10. /*
    11. Test02在com包下
    12. PackageTest01在com.dlu.javase.day01下
    13. 不在同一个包下,包名不能省略
    14. */
    15. /*
    16. 但是我们每次创建PackageTest01对象又很麻烦,那么长的类名;所以这就需要import
    17. PackageTest01 hw1 = new PackageTest01();
    18. System.out.println(hw1); //err
    19. */
    20. //import com.dlu.javase.day01.PackageTest01导入包以后,就可以省略包了
    21. PackageTest01 hw2 = new PackageTest01();
    22. System.out.println(hw2);//com.dlu.javase.day01.PackageTest01@6d06d69c
    23. }
    24. }

    ❤️解释遗留问题Scanner

    1. package com.dlu.javase.day01;
    2. import java.util.Scanner;//导包
    3. //import java.util.*;//也可以
    4. public class Test03{
    5. public static void main(String[] args){
    6. //为什么这样写?
    7. //Test03类和Scanner类不在同一个包下;java.util就是Scanner的包名
    8. //java.util.Scanner s = new java.util.Scanner(System.in);
    9. //import导包的形式
    10. Scanner s = new Scanner(System.in);
    11. String str = s.next();
    12. System.out.println("您输入的字符串是:"+str);
    13. //String为什么不需要导包呢?
    14. //因为在lang包下的直接之类都不要导入(在比如:System)
    15. java.lang.String name = "张三";
    16. String username = "李四";
    17. System.out.println(name);
    18. System.out.println(username);
    19. }
    20. }

     ❤️总结

    ⭐package(对于文本编译器)
         第一:package出现在java源文件第一行。
         第二:带有包名怎么编译?javac -d . xxx.java
         第三:怎么运行?java 完整类名
         补充:以后说类名的时候,如果带着包名描述,表示完整类名。如果没有带包,描述的话,表示简类名。例如:
            (1)java.util.Scanner 完整类名。
            (2)Scanner 简类名

    ⭐import(对于文本编译器)
          1、import什么时候不需要?
                java.lang下的不需要,同包下不需要;其它一律都需要!

          2、怎么用?
               (1)import 完整类名;

                     import java.util.Scanner; // 完整类名。

               (2)或者import 包名.*

                      import java.util.*;

                      编译器在编译的时候,会自动把*变成具体的类名

               (3)想省但也不能太省了。
                      import java.*;

                      这是不允许的,因为在java语言中规定,这里的*只代表某些类的名字

          3、不同包名下的相同类名不会冲突;例如:org.Test和com.Test不会冲突

    🥅访问控制权限修饰符

    1、访问控制权限都有哪些?4个。
            private       私有

            protected   受保护
            public        公开
            默认(什么都没有)

    2、以上的4个访问控制权限:控制的范围是什么?
           (1)private 表示私有的,只能在本类中访问

           (2)protected表示只能在本类、同包、子类中访问。

           (3)public 表示公开的,在任何位置都可以访问
           (4)“默认”表示只能在本类,以及同包下访问。
           

    1.    访问控制修饰符            本类            同包            子类            任意位置
    2.         ---------------------------------------------------------------------------
    3.         public              可以            可以            可以            可以
    4.         protected           可以            可以            可以            不行
    5.         默认                可以            可以            不行            不行
    6.         private             可以            不行            不行            不行

    范围从大到小排序:public(4) > protected(3) > 默认(2) > private(1)

    3、访问控制权限修饰符可以修饰什么?
            属性(4个都能用)
            方法(4个都能用)
            类(public和默认能用,其它不行。)
            接口(public和默认能用,其它不行。)

    ❤️例:在com.dlu包下的User类

    1. package com.dlu;
    2. public class User{
    3. // 私有的
    4. private int id;
    5. // 受保护的
    6. protected int age;
    7. // 公开的
    8. public int weight;
    9. //什么也没有,默认的
    10. String name;
    11. }

    ⭐【包没变】在User类(com.dlu)相同包下的Test(com.dlu)类:只有private修饰的不能访问;区分出来第一个private

    1. package com.dlu;
    2. public class Test{
    3. public static void main(String[] args){
    4. User u = new User();
    5. //System.out.println(u.id); // private私有的不可以访问
    6. System.out.println(u.age); //protected可以访问
    7. System.out.println(u.weight); //public可以访问
    8. System.out.println(u.name); //默认的可以访问
    9. }
    10. }

    ⭐【包变了】在User类(com.dlu)不同包下的Test01(com.dlu01)类:只有public能访问;区分出来第二个public

    1. package com.dlu01; //包变了
    2. import com.dlu.User; //导包
    3. public class Test01{
    4. public static void main(String[] args){
    5. User u = new User();
    6. System.out.println(u.id); // private私有的不可以访问
    7. //System.out.println(u.age); //protected不可以访问
    8. System.out.println(u.weight); //public修饰的可以访问
    9. //System.out.println(u.name); //默认的不可以访问
    10. }
    11. }

    ⭐【包变了】在User类(com.dlu)不同包下的Test02(com.dlu02)类,并且Test02继承User类;区分出protected

    1. package com.dlu02; //包变了
    2. import com.dlu.User; //导包
    3. //User在com.dlu包下;Test在com.dlu02包下;User和Test不在同一个包
    4. //但是Test02是User的子类
    5. public class Test02 extends User{
    6. public static void main(String[] args){
    7. Test02 t = new Test02();
    8. System.out.println(t.age); // protected修饰的可以访问
    9. //System.out.println(t.name); //默认的不能访问
    10. }
    11. }

    🥅Object类

    JDK类库的根类:Object

    ⭐这个老祖宗类中的方法我们需要先研究一下,因为这些方法都是所有子类通用的。
        任何一个类默认继承Object。就算没有直接继承,最终也会间接继承。

    ⭐Object类当中有哪些常用的方法?我们去哪里找这些方法呢?
                第一种方法:去源代码当中;但是这种方式比较麻烦,源代码也比较难;

                C:\Program Files\Java\jdk-13.0.2\lib\src\java.base\java\lang包下的Object类
                第二种方法:去查阅java的类库的帮助文档。

                例如我安装的:jdk1.8:C:\Java学习\javaSE学习\6.JDK帮助文档\jdk8-oracle官方英文-帮助文档\jdk8帮助文档\java\lang下的Object.html
    ⭐什么是API?
                应用程序编程接口。(Application Program Interface)
                整个JDK的类库(src)就是一个javase的API。
                每一个API都会配置一套API帮助文档。
                SUN公司提前写好的这套类库就是API。(一般每一份API都对应一份API帮助文档。)

    ⭐目前为止我们只需要知道这几个方法即可:
            

    1.     protected Object clone()   // 负责对象克隆的(以后接触再讲)。
    2.     int hashCode()    // 获取对象哈希值的一个方法。
    3.     boolean equals(Object obj)  // 判断两个对象是否相等
    4.     String toString()  // 将对象转换成字符串形式
    5.     protected void finalize()  // 垃圾回收器负责调用的方法

    ❤️例1:Object类的toString方法

    1、源代码

    1. public String toString() {
    2. return getClass().getName() + "@" + Integer.toHexString(hashCode());
    3. }

    toString()方法默认实现是:类名+@+对象的内存地址转换为十六进制的形式

    2、Sun公司设计toString()方法的目的是什么? 通过调用这个方法可以将一个“java对象”转换成“字符串表示形式”

    3、建议所有的子类都去重写toString()方法,toString()方法应该是一个简洁的、详实的、易阅读的 

    1. public class ObjectToString {
    2. public static void main(String[] args) {
    3. MyTime mt = new MyTime(2022,1,1);
    4. //重写toString()方法之前
    5. System.out.println(mt); //MyTime@4554617c;默认会调用toString方法
    6. //重写toString()方法之后
    7. System.out.println(mt); //2022年1月1月(简洁的、详实的、易阅读的)
    8. }
    9. }
    10. class MyTime{ //默认继承Object类
    11. private int year;
    12. private int month;
    13. private int day;
    14. //构造方法
    15. public MyTime() {
    16. }
    17. public MyTime(int year, int month, int day) {
    18. this.year = year;
    19. this.month = month;
    20. this.day = day;
    21. }
    22. //重写toString()方法
    23. public String toString(){
    24. return this.year+"年"+this.month+"月"+this.day+"月";
    25. }
    26. }

    ❤️例2:Object类的equals方法

    1、源代码

    1. public boolean equals(Object obj) {
    2.     return (this == obj);
    3. }

    2、Sun公司设计equals方法的目的是什么? 通过equals方法来判断两个对象是否相等
    3、我们需要研究一下Object类给的这个默认equals方法够不够用?(不够用) 在Object类当中的equals方法当中,默认采用的是“==”判断两个java对象是否相等; 而“==”判断的是两个java对象的内存地址我们应该判断两个java对象的内容是否相等;要使用equals方法!

    1. public class ObjectEquals {
    2. public static void main(String[] args) {
    3. //1.判断两个基本数据类型是否相等,直接用“==”
    4. // "=="是判断a中保存的100和b中保存的100是否相等
    5. int a = 10;
    6. int b = 10;
    7. System.out.println(a == b);// true
    8. //2.判断两个java对象是否相等呢?(直接用==)
    9. // 这里的“==”判断的是t1中保存的对象内存地址和t2中保存的对象内存地址是否相等
    10. MyTime01 t1 = new MyTime01(2008,8,8);
    11. MyTime01 t2 = new MyTime01(2008,8,8);
    12. System.out.println(t1 == t2);// false;
    13. // 但实际上这两个对象表示的时间是一样的,所以这两个对象应该是相同的true,
    14. // 所以不能用"=="来直接判断两个对象是否相等
    15. //3.判断两个java对象是否相等呢?(调用equals方法)
    16. //---重写equals方法之前,默认调用的是Object类的equals方法
    17. boolean bool = t1.equals(t2);//多态
    18. System.out.println(bool);
    19. //---重写equals方法之后
    20. System.out.println(t1.equals(t2));
    21. //4.目前程序有bug嘛,如果为空呢?(没有,但是效率低,进行改良)
    22. MyTime01 t3 = null;
    23. System.out.println(t1.equals(t3));
    24. //没有bug,因为下面有instanceof进行判断,空指针直接就return false
    25. }
    26. }
    27. class MyTime01 { //默认继承Object类
    28. private int year;
    29. private int month;
    30. private int day;
    31. public MyTime01() {
    32. }
    33. public MyTime01(int year, int month, int day) {
    34. this.year = year;
    35. this.month = month;
    36. this.day = day;
    37. }
    38. //-----------重写equals方法
    39. public boolean equals(Object obj) {
    40. //当年、月、日都相同,表示日期相同
    41. //获取第一个日期的年月日
    42. int year1 = this.year;
    43. int month1 = this.month;
    44. int day1 = this.day;
    45. //obj访问不到年月日,要想访问子类型中特有的东西,所以要进行向下转型
    46. if(obj instanceof MyTime01){ //判断
    47. MyTime01 mt = (MyTime01)obj;
    48. int year2 = mt.year;
    49. int month2 = mt.month;
    50. int day2 = mt.day;
    51. if(year1 == year2 && month1 == month2 && day1 == day2){
    52. return true;
    53. }
    54. }
    55. return false;
    56. }
    57. /* ------------------代码优化
    58. public boolean equals(Object obj) {
    59. //1.先判断空
    60. if(obj == null){
    61. return false;
    62. }
    63. //2.判断是不是MyTime01对象
    64. if(!(obj instanceof MyTime01)){
    65. return false;
    66. }
    67. //3.判断内存地址是否相等,内存地址相等,肯定是同一个对象
    68. if(this == obj){
    69. return true;
    70. }
    71. //4.直接进行比较
    72. MyTime01 tt = (MyTime01)obj;
    73. if(this.year == tt.year && this.month == tt.month && this.day == tt.day){
    74. return true;
    75. }
    76. return false;
    77. }
    78. */
    79. /* -------------------代码再次优化
    80. public boolean equals(Object obj) {
    81. if(obj == null || !(obj instanceof MyTime01)){
    82. return false;
    83. }
    84. if(this == obj){
    85. return true;
    86. }
    87. MyTime01 tt = (MyTime01)obj;
    88. return this.year == tt.year && this.month == tt.month && this.day == tt.day;
    89. }
    90. */
    91. /*-----------------也可以利用IDEA自动生成
    92. public String toString() {
    93. return "MyTime01{" +
    94. "year=" + year +
    95. ", month=" + month +
    96. ", day=" + day +
    97. '}';
    98. }
    99. public boolean equals(Object o) {
    100. if (this == o) return true;
    101. if (o == null || getClass() != o.getClass()) return false;
    102. MyTime01 myTime01 = (MyTime01) o;
    103. return year == myTime01.year &&
    104. month == myTime01.month &&
    105. day == myTime01.day;
    106. }
    107. */
    108. }

    ⭐比较字符串的大小

    1、java语言中的字符串String已经重写toString方法和重写equals方法

    2、比较两个两个字符串也不能使用"==";必须调用equals方法

    3、对于字符串比较大小,如果是直接写出来的,例如:String s = "abc"可以直接用"=="进行比较;如果是new出来的,例如:String s = new String("abc")就必须使用equals方法进行比较;所以我们平时就使用equals方法来判断引用数据类型,更加的通用

    4、总结java中基本数据类型比较是否相等,使用"=="

                    java中引用数据类型比较是否相等,统一使用equals方法进行判断

    1. public class ObjectEquals02 {
    2. public static void main(String[] args) {
    3. //大部分情况下,采用这样的方式创建字符串对象
    4. String s1 = "hello";
    5. String s2 = "abc";
    6. //实际上String也是一个类,不属于基本数据类型,既然是一个类一定有构造方法
    7. String s3 = new String("Test1");
    8. String s4 = new String("Test1");
    9. System.out.println(s3 == s4);//false,因为比较的是内存的地址
    10. //比较两个两个字符串也不能使用"==";必须调用重写的equals方法
    11. //对于String类已经重写了String和toString方法
    12. System.out.println(s3.equals(s4));// true
    13. //也重写了toString方法
    14. System.out.println(s3);// Test1
    15. }
    16. }

    ⭐一个综合的例题

    1. public class ObjectEquals03 {
    2. public static void main(String[] args) {
    3. Student s1 = new Student(1234,"六盘水");
    4. Student s2 = new Student(1234,"六盘水");
    5. System.out.println(s1.equals(s2)); // 多态
    6. }
    7. }
    8. class Student{
    9. private int id;
    10. private String school;
    11. //构造方法
    12. public Student() {
    13. }
    14. public Student(int id, String school) {
    15. this.id = id;
    16. this.school = school;
    17. }
    18. //当学号和学校相同,表示是同一个学生
    19. public boolean equals(Object obj){
    20. if(obj == null || !(obj instanceof Student)){
    21. return false;
    22. }
    23. if(this == obj){
    24. return true;
    25. }
    26. Student s = (Student)obj; // 向下转型
    27. return this.id == s.id && this.school.equals(s.school);
    28. }
    29. }

    ⭐equals方法深层次理解(重点掌握)

    对于equals方法我们重写要彻底!

    1. //equals方法重写要彻底
    2. public class ObjectEquals04 {
    3. public static void main(String[] args) {
    4. /*Address1 addr = new Address1("安徽","西城区","1111");
    5. User1 u = new User1("张三",addr);*/
    6. //就等价于
    7. User1 u1 = new User1("张三",new Address1("安徽","西城区","1111"));
    8. User1 u2 = new User1("张三",new Address1("安徽","西城区","1111"));
    9. System.out.println(u1.equals(u2));
    10. }
    11. }
    12. class User1{
    13. String name;
    14. Address1 addr;
    15. //构造方法
    16. public User1() {
    17. }
    18. public User1(String name, Address1 addr) {
    19. this.name = name;
    20. this.addr = addr;
    21. }
    22. //重写equals
    23. //规则:当一个用户的用户名和家庭住址都相同,表示同一个用户
    24. public boolean equals(Object obj){
    25. if(obj == null || !(obj instanceof User1)){
    26. return false;
    27. }
    28. if(this == obj){
    29. return true;
    30. }
    31. User1 u = (User1)obj;
    32. return this.name.equals(u.name) && this.addr.equals(u.addr);
    33. }
    34. }
    35. class Address1{
    36. String city;
    37. String street;
    38. String zipcode;
    39. //构造方法
    40. public Address1() {
    41. }
    42. public Address1(String city, String street, String zipcode) {
    43. this.city = city;
    44. this.street = street;
    45. this.zipcode = zipcode;
    46. }
    47. // 注意:这里如果没有重写equals方法;调用的是Object的equals方法,比较的是addr内存的地址
    48. // 这里的equals方法判断的是:Address对象和Address对象是否相等
    49. //所以这里也要重写equals,重写必须彻底!
    50. //前面String我们没有进行重写是因为默认String类已经重写了equals方法
    51. public boolean equals(Object obj) {
    52. if(obj == null || !(obj instanceof Address1)){
    53. return false;
    54. }
    55. if(this == obj){
    56. return true;
    57. }
    58. Address1 address = (Address1)obj;
    59. return this.city.equals(address.city) && this.street.equals(address.street) && this.zipcode.equals(address.zipcode);
    60. }
    61. }

    ❤️例3:Object的finalize方法(了解)

    1、在Object类中的源代码:

    1.    protected void finalize() throws Throwable { }
    2.    // GC:负责调用finalize()方法

    2、finalize()方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的

    3、这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法。

       不像equals、toString方法是需要程序员手动调用的;finalize只需要重写,重写完成后自动会有程序来调用

    4、finalize执行的时机:

       当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法

    5、finalize()方法实际上是SUN公司为java程序员准备的一个时机,垃圾销毁时机

       如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法中

    6、回顾:静态代码块的作用是什么?static{....}

       静态代码块在类加载时刻执行,并且只执行一次;这是一个SUN准备的类加载时机

       finalize()方法同样也是SUN为程序员准备的一个时机,这个时机是垃圾回收时机

    7、java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间没到等,也有可能不启动 

    1. public class ObjectFinalize {
    2. public static void main(String[] args) {
    3. /*Person1 p = new Person1();
    4. // 怎么把Person对象变成垃圾?
    5. p = null; // 这里可能就没有启动
    6. //多造点垃圾,就可以启动
    7. for(int i=0;i<1000000;i++){
    8. Person1 p1 = new Person1();
    9. p1 = null;
    10. }*/
    11. //有一段代码可以建议垃圾回收器启动
    12. Person1 p = new Person1();
    13. p = null;
    14. System.gc();// 建议启动垃圾回收器(知识启动的可能性增大了)
    15. }
    16. }
    17. class Person1{
    18. // 重写finalize方法
    19. // Person类型的对象被垃圾回收器回收的时候,垃圾回收器负责调用p.finalize();
    20. protected void finalize() throws Throwable {
    21. System.out.println(this+"即将被销毁!");
    22. }
    23. }

    ❤️例4:Object的hashCode方法

    1、在Object中的hashCode方法是怎样的?     

    1. public native int hashCode();
    2. // 这个方法不是抽象方法,带有native关键字,底层调用C++程序。

    2、hashCode()方法返回的是哈希码:

          实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值

          所以hashCode()方法的执行结果可以等同看做一个java对象的内存地址

    1. public class ObjectHashCode{
    2. public static void main(String[] args){
    3. Object o = new Object();
    4. int hashCodeValue = o.hashCode();
    5. // 对象内存地址经过哈希算法转换的一个数字。可以等同看做内存地址。
    6. System.out.println(hashCodeValue); //1163157884
    7. MyClass mc = new MyClass();
    8. int hashCodeValue2 = mc.hashCode();
    9. System.out.println(hashCodeValue2); //1956725890
    10. }
    11. }
    12. class MyClass
    13. {
    14. }

    🥅匿名内部类

    ❤️内部类概述

    匿名内部类:

           1、什么是内部类?

               内部类:在类的内部又定义了一个新的类。被称为内部类。

           2、内部类的分类:

                  静态内部类:类似于静态变量

                  实例内部类:类似于实例变量

                  局部内部类:类似于局部变量

          3、使用内部类编写的代码,可读性很差。能不用尽量不用。

          4、匿名内部类是局部内部类的一种。

                因为这个类没有名字而得名,叫做匿名内部类。

          5、学习匿名内部类主要是以后在阅读别人代码的时候,能够理解。

           并不代表以后都要这样写。因为匿名内部类有两个缺点:

               缺点1:太复杂,太乱,可读性差。

               缺点2:类没有名字,以后想重复使用,不能用。

    1. public class InnerTest01{
    2. // 静态变量
    3. static String country;
    4. //1. 静态内部类
    5. static class Inner1{
    6. }
    7. // 实例变量
    8. int age;
    9. //2. 实例内部类。
    10. class Inner2{
    11. }
    12. // 方法
    13. public void doSome(){
    14. // 局部变量
    15. int i = 100;
    16. //3. 局部内部类。
    17. class Inner3{
    18. }
    19. }
    20. public void doOther(){
    21. // doSome()方法中的局部内部类Inner3,在doOther()中不能用。
    22. }
    23. //--------------------------------------------------------------------
    24. // main方法,入口
    25. public static void main(String[] args){
    26. // 调用MyMath中的mySum方法。
    27. MyMath001 mm = new MyMath001();
    28. /*
    29. Compute c = new ComputeImpl();
    30. mm.mySum(c, 100, 200);
    31. */
    32. //代码合并
    33. //我们调用的时候里面传的是接口Compute c:mySum(Compute c, int x, int y);
    34. //所以这里调用应该需要new一个接口传进去,又因为接口是抽象类,不能new对象,
    35. //所以要写一个类ComputeImpl去实现接口,用来new对象
    36. mm.mySum(new ComputeImpl(), 100, 200);
    37. }
    38. }
    39. // 负责计算的接口
    40. interface Compute{
    41. // 抽象方法
    42. int sum(int a, int b);
    43. }
    44. // 编写一个Compute接口的实现类ComputeImpl
    45. class ComputeImpl implements Compute{
    46. // 对方法的实现
    47. public int sum(int a, int b){
    48. return a + b;
    49. }
    50. }
    51. // 数学类
    52. class MyMath001{
    53. // 数学求和方法
    54. public void mySum(Compute c, int x, int y){ //Compute c 把这个接口看成String name更好理解
    55. int retValue = c.sum(x, y);
    56. System.out.println(x + "+" + y + "=" + retValue);
    57. }
    58. }

    ❤️内部类的使用

    使用匿名内部类,下面那个ComputeImpl类实现Compute接口就不需要写了!对于匿名内部类能看懂代码就行,可读性差,且不能重复使用!

    1. public class InnerTest02{
    2. // main方法,入口
    3. public static void main(String[] args){
    4. // 调用MyMath中的mySum方法。
    5. MyMath001 mm = new MyMath001();
    6. //我们不使用Compute接口的实现类ComputeImpl;使用匿名内部类实现
    7. //mm.mySum(new ComputeImpl(), 100, 200);
    8. //使用匿名内部类,记住语法;以后能看懂就行
    9. mm.mySum(new Compute() {
    10. public int sum(int a, int b) {
    11. return a+b;
    12. }
    13. },100,200);
    14. }
    15. }
    16. // 负责计算的接口
    17. interface Compute{
    18. // 抽象方法
    19. int sum(int a, int b);
    20. }
    21. //-------使用匿名内部类,接口的实现就不需要了
    22. /*// 编写一个Compute接口的实现类ComputeImpl
    23. class ComputeImpl implements Compute{
    24. // 对方法的实现
    25. public int sum(int a, int b){
    26. return a + b;
    27. }
    28. }*/
    29. // 数学类
    30. class MyMath001{
    31. // 数学求和方法
    32. public void mySum(Compute c, int x, int y){ //Compute c 把这个接口看成String name更好理解
    33. int retValue = c.sum(x, y);
    34. System.out.println(x + "+" + y + "=" + retValue);
    35. }
    36. }

  • 相关阅读:
    JAVA计算机毕业设计中小学图书馆管理Mybatis+源码+数据库+lw文档+系统+调试部署
    java毕业生设计在线购书商城系统计算机源码+系统+mysql+调试部署+lw
    【专栏】RPC系列(理论)-协议与序列化
    速锐得适配进口福特烈马BRONCO车载 CAN总线应用随动转向大灯改装
    File的遍历文件
    Kafka生产者消息异步发送并返回发送信息api编写教程
    .Net核心级的性能优化(GC篇)
    Jetson nano 系列之7—jetson 通过rtp将视频发给远程host
    【CentOS7】安装docker
    Linux系统编程 day02 vim、gcc、库的制作与使用
  • 原文地址:https://blog.csdn.net/m0_61933976/article/details/125577514