目录
类(class)的第一个功能是隔离,起到边界的作用,使得不同功能的代码互不干扰。
在非面向对象的语言中,我们主要定义结构和函数来实现功能。下边用C语言来举个例子。
某程序员写了宠物模拟器,不过开始他只有一只狗,于是他写了一个只有狗子特性的代码,代码功能就是模拟模拟狗子被撸后,会㕵㕵叫:
注:C语言代码使用Visual Studio编写。
- #include
- #include
-
- const wchar_t* name = L"旺才";
-
- void call() {
- wprintf(L"%s,过来!\n",name);
- }
-
- void pat() {
- wprintf(L"汪汪\n");
- }
-
- void main() {
- setlocale(LC_ALL, "");
- wprintf(L"撸狗\n-----------\n");
- call();
- pat();
- }
运行结果:

此时这个程序没啥问题,接着又养了一只猫,猫跟狗差不多的功能,但我们不能重复定义call()和pat()函数,这样会有冲突,那需要对代码做些改动,可以接受两只宠物。
这里至少有两种思路,一种是再复制狗的代码,改下名称;另一种,保持函数名称不变,添加参数进行区别。
对于前者,可能改成这样:
- #include
- #include
-
- const wchar_t* dog_name = L"旺才";
- const wchar_t* cat_name = L"花花";
-
- void dog_call() {
- wprintf(L"%s,过来!\n", dog_name);
- }
-
- void cat_call() {
- wprintf(L"%s,过来!\n", cat_name);
- }
-
- void dog_pat() {
- wprintf(L"汪汪\n");
- }
-
- void cat_pat() {
- wprintf(L"喵喵\n");
- }
- void main() {
- setlocale(LC_ALL, "");
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n')
- wprintf(L">>\n请选择宠物:狗(d),猫(c)\n");
- c = getchar();
- if (c == '\n') continue;
- if (c == 'd') {
- wprintf(L"撸狗\n-----------\n");
- dog_call();
- dog_pat();
- }
- else if (c == 'c') {
- wprintf(L"撸猫\n-----------\n");
- cat_call();
- cat_pat();
- }
- else if (c != 'q') {
- wprintf(L"所先宠物不存在\n");
- }
- }
- }
运行结果:

另一种改成这样:
- #include
- #include
-
- const wchar_t* dog_name = L"旺才";
- const wchar_t* cat_name = L"花花";
-
- void call(char pet) {
- if (pet == 'd')
- wprintf(L"%s,过来!\n", dog_name);
- else if (pet == 'c')
- wprintf(L"%s,过来!\n", cat_name);
- else
- wprintf(L"所选宠物不存在\n");
- }
-
- void pat(char pet) {
- if (pet == 'd')
- wprintf(L"汪汪\n");
- else if (pet == 'c')
- wprintf(L"喵喵\n");
- }
-
- void main() {
- setlocale(LC_ALL, "");
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n')
- wprintf(L">>\n请选择宠物:狗(d),猫(c)\n");
- c = getchar();
- if (c == '\n') continue;
- if (c == 'd') {
- wprintf(L"撸狗\n-----------\n");
- }
- else if (c == 'c') {
- wprintf(L"撸猫\n-----------\n");
- }
- call(c);
- pat(c);
-
- }
- }
运行结果:

前者命名冲突,代码重复。好处是比较直观,小白都能看懂。
后者代码整洁,但交叉比较,耦合性高,牵一发可能动全身。
不管用哪一种代码改动,多多少少都会对别的部分形成干扰,虽然有方法尽量去避免这些干扰,但往往对程序员的要求太高,反而降低了开发效率。产生干扰的主要原因是,C语言只能做到函数级别的代码分组,增加功能就要不断地增加函数,当函数的数据到达一定级别时,名称的冲突必然导致系统的不可维护。我们可以想像一下,当这个程序有了几百上千种宠物后,代码会是什么样子的?
类实现了更大范围的代码分组,将相关的函数变成成员方法,将全局变量变成成员字段放在一个类中,与其它代码隔离开来,在小范围内可以有效地避开命名冲突的问题。就好比,行政区中全国乡镇的名称重复的很多,但在同一个区县中就不存在了。为了区分同名的乡镇,我们只要区分区县就可以了。所以前边的代码,用java的方式,我们就可以写成两个类,一个Dog类,一个Cat类,虽然他们有相同的部分,但互不干扰。
- /**
- * 狗狗
- *
- */
- public class Dog {
- private static String name = "旺财";
-
- public static void call() {
- System.out.format("%s\n", name);
- }
-
- public static void pat() {
- System.out.println("汪汪!");
- }
-
- }
- /**
- * 猫猫
- *
- */
- public class Cat {
-
- private static String name = "花花";
-
- public static void call() {
- System.out.format("%s\n", name);
- }
-
- /**
- * 猫会妙妙
- */
- public static void pat() {
- System.out.println("喵喵");
- }
- }
- import java.io.IOException;
-
- public class App {
-
- public static void main(String[] args) throws IOException {
-
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n' && c != '\r')
- System.out.println(">>\n请选择宠物:狗(d),猫(c)\n");
-
- c = (char) System.in.read();
- if (c == '\n' || c == '\r')
- continue;
- if (c == 'd') {
- System.out.println("撸狗\n-----------\n");
- Dog.call();
- Dog.pat();
- } else if (c == 'c') {
- System.out.println("撸猫\n-----------\n");
- Cat.call();
- Cat.pat();
- } else if (c != 'q') {
- System.out.println("所先宠物不存在\n");
- }
-
- }
- }
-
- }
运行结果:

Math (Java SE 17 & JDK 17)declaration: module: java.base, package: java.lang, class: Math
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Math.html System (Java SE 17 & JDK 17)declaration: module: java.base, package: java.lang, class: System
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/System.html
用Java重构之后,加宠物就方便很多了,只要类不重名,其它代码随便写。比如增加一个Parrot类:
- /**
- * 鹦鹉
- *
- */
- public class Parrot {
-
- private static String name = "鹦哥";
-
- public static void call() {
- System.out.format("%s\n", name);
- }
-
- public static void pat() {
- System.out.println("烦死了!");
- }
-
- }
修改App.java
- import java.io.IOException;
-
- public class App {
-
- public static void main(String[] args) throws IOException {
-
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n' && c != '\r')
- System.out.println(">>\n请选择宠物:狗(d),猫(c),鹦鹉(p)\n");
-
- c = (char) System.in.read();
- if (c == '\n' || c == '\r')
- continue;
- if (c == 'd') {
- System.out.println("撸狗\n-----------\n");
- Dog.call();
- Dog.pat();
- } else if (c == 'c') {
- System.out.println("撸猫\n-----------\n");
- Cat.call();
- Cat.pat();
- } else if (c == 'p') {
- System.out.println("撸鹦鹉\n-----------\n");
- Parrot.call();
- Parrot.pat();
- } else if (c != 'q') {
- System.out.println("所先宠物不存在\n");
- }
-
- }
- }
-
- }
运行结果:

前边,虽然解决了代码中的某些命名冲突的问题,但有个最大的缺点,就是重复率太高,如果不看具体实现,字段、方法的名称几乎是一样的。其实这些内容是可以做到重用的,Java的代码重用除了传统的定义数据结构和通用函数外,还可以类型化(Type)及继承。
前边的示例中,一个类只实现了一个宠物的行为,如果又增加了一只狗狗,是不是要增加一个类,比如Dog1,其实大可不必。前边之所以只能表述一个宠物,是因为类的成员都标成了static,意思就是这个类中的代码跟面向过程没啥差别,只是调用前需要加上类名作为前辍。增加的狗狗目前来说,可能只是名字不一样,所以只要一个狗狗类的模板即可。
Java的类除了分组的作用,本身也是可以作为一个数据类型来使用的,此时只要将类成员的static关键去掉即可。接下来改下Dog类、Cat类和Parrot类。
Dog类
- /**
- * 狗狗
- *
- */
- public class Dog {
- private String name = "旺财";
-
- public void call() {
- System.out.format("%s\n", name);
- }
-
- public void pat() {
- System.out.println("汪汪!");
- }
-
- }
Cat类
- /**
- * 猫猫
- *
- */
- public class Cat {
-
- private String name = "花花";
-
- public void call() {
- System.out.format("%s\n", name);
- }
-
- /**
- * 猫会妙妙
- */
- public void pat() {
- System.out.println("喵喵");
- }
- }
- /**
- * 鹦鹉
- *
- */
- public class Parrot {
-
- private String name = "鹦哥";
-
- public void call() {
- System.out.format("%s\n", name);
- }
-
- public void pat() {
- System.out.println("烦死了!");
- }
-
- }
此时,各个类就成类型(Type)结构了,如果调用这些代码,就得先创建类型实例,更改App类的代码,变成这样:
- import java.io.IOException;
-
- public class App {
-
- public static void main(String[] args) throws IOException {
-
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n' && c != '\r')
- System.out.println(">>\n请选择宠物:狗(d),猫(c),鹦鹉(p)\n");
-
- c = (char) System.in.read();
- if (c == '\n' || c == '\r')
- continue;
- if (c == 'd') {
- System.out.println("撸狗\n-----------\n");
- Dog dog = new Dog();
- dog.call();
- dog.pat();
- } else if (c == 'c') {
- System.out.println("撸猫\n-----------\n");
- Cat cat = new Cat();
- cat.call();
- cat.pat();
- } else if (c == 'p') {
- System.out.println("撸鹦鹉\n-----------\n");
- Parrot parrot = new Parrot();
- parrot.call();
- parrot.pat();
- } else if (c != 'q') {
- System.out.println("所先宠物不存在\n");
- }
- }
- }
-
- }
虽然多了点代码,但我们可以复用这个结构,只要做少量的修改,就可以创建无数个宠物。改一下Dog类,增加两个构造器,一个是默认的无参数,另一个是带参数的,这样可以创建对象的修改狗狗的名字:
- /**
- * 狗狗
- *
- */
- public class Dog {
- private String name = "旺财";
-
- public Dog() {
-
- }
-
- public Dog(String dogName) {
- name = dogName;
- }
-
- public void call() {
- System.out.format("%s\n", name);
- }
-
- public void pat() {
- System.out.println("汪汪!");
- }
-
- }
App类
- import java.io.IOException;
-
- public class App {
-
- public static void main(String[] args) throws IOException {
-
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n' && c != '\r')
- System.out.println(">>\n请选择宠物:狗(d),猫(c),鹦鹉(p)\n");
-
- c = (char) System.in.read();
- if (c == '\n' || c == '\r')
- continue;
- if (c == 'd') {
- System.out.println("撸两条狗\n-----------\n");
- Dog dog = new Dog();
- dog.call();
- dog.pat();
-
- Dog dog1 = new Dog("小贝");
- dog1.call();
- dog1.pat();
- } else if (c == 'c') {
- System.out.println("撸猫\n-----------\n");
- Cat cat = new Cat();
- cat.call();
- cat.pat();
- } else if (c == 'p') {
- System.out.println("撸鹦鹉\n-----------\n");
- Parrot parrot = new Parrot();
- parrot.call();
- parrot.pat();
- } else if (c != 'q') {
- System.out.println("所先宠物不存在\n");
- }
- }
- }
-
- }
运行效果:

另一种代码重用的方式就是继承了,上述示例中无论狗狗、猫咪还是鹦鹉,它们行为方式是一样的,都是撸完后做出打出一行文本,无非就是内容上的差别,我们可以相同的部分提取出,单独创建一类在存放,响应内容的由具体的宠物类中实现,我们创建一个Pet类:
- /**
- * 小可爱们
- *
- */
- public class Pet {
- private String name = "无名";// 宠物都有名字
-
- public Pet() {
-
- }
-
- public Pet(String petName) {
- name = petName;
- }
-
- public void call() {
- System.out.format("%s\n", name);
- }
-
- public void pat() {
- System.out.println(response());
- }
-
- /**
- * 默认没反应,由具体对象实现
- * @return
- */
- protected String response() {
- return "";
- }
- }
然后修改各个宠物类:
- /**
- * 狗狗
- *
- */
- public class Dog extends Pet {
- public Dog() {
- super();
- }
-
- public Dog(String dogName) {
- super(dogName);
- }
-
- @Override
- protected String response() {
- return "汪汪!";
- }
-
- }
- /**
- * 猫猫
- *
- */
- public class Cat extends Pet {
-
- public Cat() {
- this("花花");
- }
-
- public Cat(String catName) {
- super(catName);
- }
-
- @Override
- protected String response() {
- return "喵喵!";
- }
-
- }
- /**
- * 鹦鹉
- *
- */
- public class Parrot extends Pet {
-
- public Parrot() {
- this("鹦哥");
- }
-
- public Parrot(String parrotName) {
- super(parrotName);
- }
-
- @Override
- protected String response() {
- return "烦死了!";
- }
-
- }
运行结果:

为了实现代码的重用,实际还是有点代价的,代码的结构及语法都复杂了不少,但有了IDE的支撑,以后往后代码的增多,这点代价还是非常值的。接下来可以尝试增加两个宠物,一个是黄金莽,另一个是猫的细分种类咖啡猫。
对于黄金莽,即不需要名字,也不会发声,代码可以写成这样,基本上不用写什么代码:
- /**
- * 黄金莽
- *
- */
- public class GoldBoa extends Pet {
- public GoldBoa() {
- super("");
- }
-
- }
对于 咖啡猫,除了跟普通猫一样,还会说人话:
- /**
- * 咖啡猫
- *
- */
- public class Garfield extends Cat {
- public Garfield() {
- super("");
- }
-
- public Garfield(String name) {
- super(name);
- }
-
- public void speak() {
- System.out.print("我会说话!");
- }
- }
修改一下App,创建新的宠物:
- import java.io.IOException;
-
- public class App {
-
- public static void main(String[] args) throws IOException {
-
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n' && c != '\r')
- System.out.println(">>\n请选择宠物:狗(d),猫(c),鹦鹉(p),黄金莽(b)\n");
-
- c = (char) System.in.read();
- if (c == '\n' || c == '\r')
- continue;
- if (c == 'd') {
- System.out.println("撸两条狗\n-----------\n");
- Dog dog = new Dog();
- dog.call();
- dog.pat();
-
- Dog dog1 = new Dog("小贝");
- dog1.call();
- dog1.pat();
- } else if (c == 'c') {
- System.out.println("撸猫\n-----------\n");
- Cat cat = new Cat();
- cat.call();
- cat.pat();
-
- Garfield garfield = new Garfield();
- garfield.call();
- garfield.pat();
- garfield.speak();
-
- } else if (c == 'p') {
- System.out.println("撸鹦鹉\n-----------\n");
- Parrot parrot = new Parrot();
- parrot.call();
- parrot.pat();
- } else if (c == 'b') {
- System.out.println("撸黄金莽\n-----------\n");
- GoldBoa boa = new GoldBoa();
- boa.call();
- boa.pat();
- } else if (c != 'q') {
- System.out.println("所先宠物不存在\n");
- }
- }
- }
-
- }
运行结果:

代码进行分组后,还可以对内部成员进行访问控制。这样可以对代码进行更多的约束控制,上述示例中,每个宠物都有自己的名字,名字一旦起好,别人就不能随意发动了,所以在定义类的时候,name这个字段前边加上了private这个修饰符,说明不能被外部更改,因为加了这个修饰后,程序运行起来后,这个代码对外部的代码是不可见的。就好比路上见到一个人,你不知道这个有没有带钱包,因为钱包是私有的,一般是不让外人看到的。
宠物的名字虽然不可修改,但我们还是可以得到宠物的名字的,然后修改一下Pet类,增加一个获取名字的方法,这个方法是公开的,也就说谁都可以知道宠物的名字,所以前边加了一个修改符public:
- /**
- * 小可爱们
- *
- */
- public class Pet {
- private String name = "无名";// 宠物都有名字
-
- public Pet() {
-
- }
-
- public Pet(String petName) {
- name = petName;
- }
-
- public String getName() {
- return name;
- }
-
- public void call() {
- System.out.format("%s\n", name);
- }
-
- public void pat() {
- System.out.println(response());
- }
-
- /**
- * 默认没反应,由具体对象实现
- *
- * @return
- */
- protected String response() {
- return "";
- }
- }
再改下App类:
- import java.io.IOException;
-
- public class App {
-
- public static void main(String[] args) throws IOException {
-
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n' && c != '\r')
- System.out.println(">>\n请选择宠物:狗(d),猫(c),鹦鹉(p),黄金莽(b)\n");
-
- c = (char) System.in.read();
- if (c == '\n' || c == '\r')
- continue;
- if (c == 'd') {
- System.out.println("撸两条狗\n-----------\n");
- Dog dog = new Dog();
- System.out.format("宠物名字:%s\n",dog.getName());
- dog.call();
- dog.pat();
-
- Dog dog1 = new Dog("小贝");
- System.out.format("宠物名字:%s\n",dog1.getName());
- dog1.call();
- dog1.pat();
- } else if (c == 'c') {
- System.out.println("撸猫\n-----------\n");
- Cat cat = new Cat();
- System.out.format("宠物名字:%s\n",cat.getName());
- cat.call();
- cat.pat();
-
- Garfield garfield = new Garfield();
- System.out.format("宠物名字:%s\n",garfield.getName());
- garfield.call();
- garfield.pat();
- garfield.speak();
-
- } else if (c == 'p') {
- System.out.println("撸鹦鹉\n-----------\n");
- Parrot parrot = new Parrot();
- System.out.format("宠物名字:%s\n",parrot.getName());
- parrot.call();
- parrot.pat();
- } else if (c == 'b') {
- System.out.println("撸黄金莽\n-----------\n");
- GoldBoa boa = new GoldBoa();
- System.out.format("宠物名字:%s\n",boa.getName());
- boa.call();
- boa.pat();
- } else if (c != 'q') {
- System.out.println("所先宠物不存在\n");
- }
- }
- }
-
- }
运行效果:

protected这个关键字是继承时专用的。表示可以提供给子类访问,这样的话就可以将一些方法让子类调用、重写或实现。之前代码中已经在Pet类中定义了一个叫做response()的方法,这个方法在App中是不可见的,但Dog、Cat等类中是可以访问的。具体请查看之前的代码,这里不复述。
之前,我们撸宠物的时候,宠物是直接做出反应的,但有时候可能是反应迟钝的,这时可以用线程来模拟一下,线程需要写一个类实现Runnable接口,但这种反应是每个动物特有的,所以不必定义全局类,只定义一个内部类来实现,以狗子举例:
- /**
- * 狗狗
- *
- */
- public class Dog extends Pet {
- public Dog() {
- this("汪财");
- }
-
- public Dog(String dogName) {
- super(dogName);
- }
-
- @Override
- protected String response() {
- return "汪汪!";
- }
-
- @Override
- public void pat() {
- Thread daze = new Thread(new DogResponse());
- daze.start();
- }
-
- class DogResponse implements Runnable {
-
- @Override
- public void run() {
- try {
- System.out.println("先发个呆!");
- Thread.sleep(3000);
- System.out.println(response());
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- }
-
- }
-
- }
为了方便起见,再改下App, 去掉一只狗狗:
- import java.io.IOException;
-
- public class App {
-
- public static void main(String[] args) throws IOException {
-
- char c = '0';
-
- while (c != 'q') {
- if (c != '\n' && c != '\r')
- System.out.println(">>\n请选择宠物:狗(d),猫(c),鹦鹉(p),黄金莽(b)\n");
-
- c = (char) System.in.read();
- if (c == '\n' || c == '\r')
- continue;
- if (c == 'd') {
- System.out.println("撸两条狗\n-----------\n");
- Dog dog = new Dog();
- System.out.format("宠物名字:%s\n",dog.getName());
- dog.call();
- dog.pat();
-
- } else if (c == 'c') {
- System.out.println("撸猫\n-----------\n");
- Cat cat = new Cat();
- System.out.format("宠物名字:%s\n",cat.getName());
- cat.call();
- cat.pat();
-
- Garfield garfield = new Garfield();
- System.out.format("宠物名字:%s\n",garfield.getName());
- garfield.call();
- garfield.pat();
- garfield.speak();
-
- } else if (c == 'p') {
- System.out.println("撸鹦鹉\n-----------\n");
- Parrot parrot = new Parrot();
- System.out.format("宠物名字:%s\n",parrot.getName());
- parrot.call();
- parrot.pat();
- } else if (c == 'b') {
- System.out.println("撸黄金莽\n-----------\n");
- GoldBoa boa = new GoldBoa();
- System.out.format("宠物名字:%s\n",boa.getName());
- boa.call();
- boa.pat();
- } else if (c != 'q') {
- System.out.println("所先宠物不存在\n");
- }
- }
- }
-
- }
运行效果:

如果嫌定义内部类麻烦的话,也可以使用匿名类,使代码更紧凑一点,狗狗的代码变成了这样:
- /**
- * 狗狗
- *
- */
- public class Dog extends Pet {
- public Dog() {
- this("汪财");
- }
-
- public Dog(String dogName) {
- super(dogName);
- }
-
- @Override
- protected String response() {
- return "汪汪!";
- }
-
- @Override
- public void pat() {
- Thread daze = new Thread(new Runnable() {
-
- @Override
- public void run() {
- try {
- System.out.println("先发个呆!");
- Thread.sleep(3000);
- System.out.println("3秒后......");
- System.out.println(response());
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- });
- daze.start();
- }
-
- }
运行效果同上。
宠物养了就是玩的,有时候会让宠物表演,当然不是真的表演,而随机做一些动物,我们可以定义一个类来存放宠物表演时的状态,但表演也是经常性的,而且仅仅是表演时用到,所以不必定义一个全局类来表示这些动作,也不用定义内部类,别的地方用不到,因而可以直接在方法内定义一个局部类,以狗狗为例:
- /**
- * 狗狗
- *
- */
- public class Dog extends Pet {
- public Dog() {
- this("汪财");
- }
-
- public Dog(String dogName) {
- super(dogName);
- }
-
- @Override
- protected String response() {
- return "汪汪!";
- }
-
- public void performence() {
- class Actions {
- public int times = 0;
-
- public void bark() {
- System.out.println("汪汪!汪汪汪!");
- }
-
- public void sit() {
- System.out.println("坐下了!");
- }
-
- public void jump() {
- System.out.println("上屋顶了!");
- }
- }
- System.out.println("----------开始表演--------------");
- Actions actions = new Actions();
- while (actions.times < 5) {
- int order = (int) Math.ceil(Math.random() * 3);
- switch (order) {
- case 1:
- actions.bark();
- break;
- case 2:
- actions.sit();
- case 3:
- actions.jump();
- }
- actions.times++;
- }
- System.out.println("----------表演结束--------------");
- }
-
- @Override
- public void pat() {
- Thread daze = new Thread(new Runnable() {
-
- @Override
- public void run() {
- try {
- System.out.println("先发个呆!");
- Thread.sleep(3000);
- System.out.println("3秒后......");
- System.out.println(response());
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- });
- daze.start();
- }
-
- }
运行效果:

类是用来分组代码功能的,有时候会有一些使用范围比较小的代码,而又要对其按功能分组,就可以使用上述的实现方法。
本文刚开始的时候,定义的类成员都是加了static的,static表示程序一运行,这些代码就可以直接使用的,仅仅加上类名作前缀即可。如果不加就要先做new的这个动作,才能使用。也就是static与非static是两个不同的东西。因为先有static,所以在new出来的对象实例中使用static成员,反之则不能,很可能实例还没创建,没东西可用,即使他们在一个类里边。
顶层类不能加static修饰,但内部类却可以。
匿名类有些情况下可以使用Lamda来表达,这样可以使代码更加紧凑。比如前边狗狗被的反应可以变成这样(Thead类的构造方法参数):
- /**
- * 狗狗
- *
- */
- public class Dog extends Pet {
- public Dog() {
- this("汪财");
- }
-
- public Dog(String dogName) {
- super(dogName);
- }
-
- @Override
- protected String response() {
- return "汪汪!";
- }
-
- public void performence() {
- class Actions {
- public int times = 0;
-
- public void bark() {
- System.out.println("汪汪!汪汪汪!");
- }
-
- public void sit() {
- System.out.println("坐下了!");
- }
-
- public void jump() {
- System.out.println("上屋顶了!");
- }
- }
- System.out.println("----------开始表演--------------");
- Actions actions = new Actions();
- while (actions.times < 5) {
- int order = (int) Math.ceil(Math.random() * 3);
- switch (order) {
- case 1:
- actions.bark();
- break;
- case 2:
- actions.sit();
- case 3:
- actions.jump();
- }
- actions.times++;
- }
- System.out.println("----------表演结束--------------");
- }
-
- @Override
- public void pat() {
- Thread daze = new Thread(() -> {
-
- try {
- System.out.println("先发个呆!");
- Thread.sleep(3000);
- System.out.println("3秒后......");
- System.out.println(response());
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- });
- daze.start();
- }
-
- }
用Lamda只要写run()中的代码就可以了。
概念这东西,很多时候是用的一些新造的词来描述的,Java是一门面向对象的语言,面向对象这东西从字面上并不是很好理解。封装是什么?继承是什么?多态是什么?并不太好用自然语言来表达,多数解释也只是说明了其意图,并不能解释是如何实现的。其实代码写多了,也就那么回事。