怒肝俩月,新鲜出炉史上最有趣的Java小白手册,第一版,每个 Java 初学者都应该收藏(14)

简介: 怒肝俩月,新鲜出炉史上最有趣的Java小白手册,第一版,每个 Java 初学者都应该收藏

03、作为参数传递


在下例中,有一个无参的构造方法,里面调用了 print() 方法,参数只有一个 this 关键字。


public class ThisTest {
    public ThisTest() {
        print(this);
    }
    private void print(ThisTest thisTest) {
        System.out.println("print " +thisTest);
    }
    public static void main(String[] args) {
        ThisTest test = new ThisTest();
        System.out.println("main " + test);
    }
}


来打印看一下结果:


print com.cmower.baeldung.this1.ThisTest@573fd745

main com.cmower.baeldung.this1.ThisTest@573fd745

1

2

从结果中可以看得出来,this 就是我们在 main() 方法中使用 new 关键字创建的 ThisTest 对象。


04、链式调用


学过 JavaScript,或者 jQuery 的读者可能对链式调用比较熟悉,类似于 a.b().c().d(),仿佛能无穷无尽调用下去。


在 Java 中,对应的专有名词叫 Builder 模式,来看一个示例。


public class Writer {
    private int age;
    private String name;
    private String bookName;
    public Writer(WriterBuilder builder) {
        this.age = builder.age;
        this.name = builder.name;
        this.bookName = builder.bookName;
    }
    public static class WriterBuilder {
        public String bookName;
        private int age;
        private String name;
        public WriterBuilder(int age, String name) {
            this.age = age;
            this.name = name;
        }
        public WriterBuilder writeBook(String bookName) {
            this.bookName = bookName;
            return this;
        }
        public Writer build() {
            return new Writer(this);
        }
    }
}


Writer 类有三个成员变量,分别是 age、name 和 bookName,还有它们仨对应的一个构造方法,参数是一个内部静态类 WriterBuilder。


内部类 WriterBuilder 也有三个成员变量,和 Writer 类一致,不同的是,WriterBuilder 类的构造方法里面只有 age 和 name 赋值了,另外一个成员变量 bookName 通过单独的方法 writeBook() 来赋值,注意,该方法的返回类型是 WriterBuilder,最后使用 return 返回了 this 关键字。


最后的 build() 方法用来创建一个 Writer 对象,参数为 this 关键字,也就是当前的 WriterBuilder 对象。


这时候,创建 Writer 对象就可以通过链式调用的方式。


Writer writer = new Writer.WriterBuilder(18,"沉默王二")

               .writeBook("《Web全栈开发进阶之路》")

               .build();



05、在内部类中访问外部类对象


说实话,自从 Java 8 的函数式编程出现后,就很少用到 this 在内部类中访问外部类对象了。来看一个示例:


public class ThisInnerTest {
    private String name;
    class InnerClass {
        public InnerClass() {
            ThisInnerTest thisInnerTest = ThisInnerTest.this;
            String outerName = thisInnerTest.name;
        }
    }
}



在内部类 InnerClass 的构造方法中,通过外部类.this 可以获取到外部类对象,然后就可以使用外部类的成员变量了,比如说 name。


super 关键字


简而言之,super 关键字就是用来访问父类的。


先来看父类:


public class SuperBase {
    String message = "父类";
    public SuperBase(String message) {
        this.message = message;
    }
    public SuperBase() {
    }
    public void printMessage() {
        System.out.println(message);
    }
}


再来看子类:


public class SuperSub extends SuperBase {
    String message = "子类";
    public SuperSub(String message) {
        super(message);
    }
    public SuperSub() {
        super.printMessage();
        printMessage();
    }
    public void getParentMessage() {
        System.out.println(super.message);
    }
    public void printMessage() {
        System.out.println(message);
    }
}



1)super 关键字可用于访问父类的构造方法


你看,子类可以通过 super(message) 来调用父类的构造方法。现在来新建一个 SuperSub 对象,看看输出结果是什么:


SuperSub superSub = new SuperSub("子类的message");

1

new 关键字在调用构造方法创建子类对象的时候,会通过 super 关键字初始化父类的 message,所以此此时父类的 message 会输出“子类的message”。


2)super 关键字可以访问父类的变量


上述例子中的 SuperSub 类中就有,getParentMessage() 通过 super.message 方法父类的同名成员变量 message。


3)当方法发生重写时,super 关键字可以访问父类的同名方法


上述例子中的 SuperSub 类中就有,无参的构造方法 SuperSub() 中就使用 super.printMessage() 调用了父类的同名方法。


十四、重写和重载


先来看一段重写的代码吧。


class LaoWang{
    public void write() {
        System.out.println("老王写了一本《基督山伯爵》");
    }
}
public class XiaoWang extends LaoWang {
    @Override
    public void write() {
        System.out.println("小王写了一本《茶花女》");
    }
}


重写的两个方法名相同,方法参数的个数也相同;不过一个方法在父类中,另外一个在子类中。就好像父类 LaoWang 有一个 write() 方法(无参),方法体是写一本《基督山伯爵》;子类 XiaoWang 重写了父类的 write() 方法(无参),但方法体是写一本《茶花女》。


来写一段测试代码。


public class OverridingTest {

   public static void main(String[] args) {

       LaoWang wang = new XiaoWang();

       wang.write();

   }

}



大家猜结果是什么?


小王写了一本《茶花女》

1

在上面的代码中,们声明了一个类型为 LaoWang 的变量 wang。在编译期间,编译器会检查 LaoWang 类是否包含了 write() 方法,发现 LaoWang 类有,于是编译通过。在运行期间,new 了一个 XiaoWang 对象,并将其赋值给 wang,此时 Java 虚拟机知道 wang 引用的是 XiaoWang 对象,所以调用的是子类 XiaoWang 中的 write() 方法而不是父类 LaoWang 中的 write() 方法,因此输出结果为“小王写了一本《茶花女》”。


再来看一段重载的代码吧。


class LaoWang{

   public void read() {

       System.out.println("老王读了一本《Web全栈开发进阶之路》");

   }

 

   public void read(String bookname) {

       System.out.println("老王读了一本《" + bookname + "》");

   }

}



重载的两个方法名相同,但方法参数的个数不同,另外也不涉及到继承,两个方法在同一个类中。就好像类 LaoWang 有两个方法,名字都是 read(),但一个有参数(书名),另外一个没有(只能读写死的一本书)。


来写一段测试代码。


public class OverloadingTest {

   public static void main(String[] args) {

       LaoWang wang = new LaoWang();

       wang.read();

       wang.read("金瓶梅");

   }

}



这结果就不用猜了。变量 wang 的类型为 LaoWang,wang.read() 调用的是无参的 read() 方法,因此先输出“老王读了一本《Web全栈开发进阶之路》”;wang.read("金瓶梅") 调用的是有参的 read(bookname) 方法,因此后输出“老王读了一本《金瓶梅》”。在编译期间,编译器就知道这两个 read() 方法时不同的,因为它们的方法签名(=方法名称+方法参数)不同。


简单的来总结一下:


1)编译器无法决定调用哪个重写的方法,因为只从变量的类型上是无法做出判断的,要在运行时才能决定;但编译器可以明确地知道该调用哪个重载的方法,因为引用类型是确定的,参数个数决定了该调用哪个方法。


2)多态针对的是重写,而不是重载。




哎,后悔啊,早年我要是能把这道面试题吃透的话,也不用被老马刁难了。吟一首诗感慨一下人生吧。


青青园中葵,朝露待日晞。

阳春布德泽,万物生光辉。

常恐秋节至,焜黄华叶衰。

百川东到海,何时复西归?

少壮不努力,老大徒伤悲

另外,我想要告诉大家的是,重写(Override)和重载(Overload)是 Java 中两个非常重要的概念,新手经常会被它们俩迷惑,因为它们俩的英文名字太像了,中文翻译也只差一个字。难,太难了。



相关文章
|
2月前
|
算法 Java
「译文」Java 垃圾收集参考手册(四):Serial GC
「译文」Java 垃圾收集参考手册(四):Serial GC
|
2月前
|
算法 Java PHP
「译文」Java 垃圾收集参考手册(一):垃圾收集简介
「译文」Java 垃圾收集参考手册(一):垃圾收集简介
|
2月前
|
网络协议 Java Maven
Java自救手册
Java自救手册
57 2
|
4月前
|
算法 Java 程序员
火爆Boss直聘的2023最牛字节Java面试手册!助你狂拿千份offer!
当下程序员现状 根据一些调查报告,可以了解到当下程序员的现状。 首先,从年龄分布来看,年轻的程序员占据了主导地位。 30岁以下的开发者占比最高,为81%,而40岁以上的开发者仅占3%。 这意味着,程序员这个行业在一定程度上是年轻化的,同时也面临着一些中年转行或者技术更新换代的问题。 在性别方面,男性程序员的比例在90%以上,女性程序员的比例较低。 这可能和传统观念中将程序员视为男性职业有关。然而,随着技术的普及和女性对计算机科学的兴趣逐渐提高,女性程序员的比例也在逐渐增加。 从职业发展来看,程序员的职业发展相对较慢。 虽然程序员的薪资普遍较高,但是工作压力也很大,需要不断学习和更
89 0
|
2月前
|
算法 安全 Java
「译文」Java 垃圾收集参考手册(三):GC 算法基础篇
「译文」Java 垃圾收集参考手册(三):GC 算法基础篇
|
2月前
|
算法 Java
「译文」Java 垃圾收集参考手册(五):Parallel GC
「译文」Java 垃圾收集参考手册(五):Parallel GC
|
2月前
|
算法 Java
「译文」Java 垃圾收集参考手册(六):Concurrent Mark and Sweep
「译文」Java 垃圾收集参考手册(六):Concurrent Mark and Sweep
|
2月前
|
存储 算法 Java
「译文」Java 垃圾收集参考手册(七):Garbage First
「译文」Java 垃圾收集参考手册(七):Garbage First
|
2月前
|
算法 Java
「译文」Java 垃圾收集参考手册(八):GC 算法总结
「译文」Java 垃圾收集参考手册(八):GC 算法总结
|
2月前
|
存储 监控 算法
「译文」Java 垃圾收集参考手册(九):GC 调优基础篇
「译文」Java 垃圾收集参考手册(九):GC 调优基础篇