Java 复习整理day05
阅读原文时间:2023年07月09日阅读:1

1 package com.it.demo01_oop;
2
3 import java.util.Arrays;
4
5 /*
6 案例: 演示面向过程和面向对象代码的区别
7
8 面向过程编程思想详解:
9 面向过程思想其实就是一种编程思想. 所谓的面向过程开发, 指的就是面向着具体的每一个步骤和过程, 把每一个步骤和过程完成,
10 然后由这些功能方法相互调用, 完成需求.
11
12 记忆: 面向过程的代表语言是: C语言.
13
14 面向对象编程思想详解:
15 //推荐答题思路: 概述, 思想特点, 举例, 总结.
16
17 首先, 面向对象是一种编程思想, 它是基于面向过程的, 强调的是以 对象 为基础, 完成各种操作.
18 说道面向对象不得不提的就是它的3大思想特点:
19 1. 把复杂的事情简单化.
20 2. 更符合人们的思考习惯.
21 3. 把程序员从执行者变成指挥者.
22 举个例子吧, 买电脑, 洗衣服 (例子越契合当时的场景, 案例价值越高)
23 总结: 万物接对象.
24
25 程序开发:
26 就是在不断的创建对象, 使用对象, 指挥对象做事情.
27
28 程序设计:
29 就是在维护 对象 和 对象之间的关系.
30 */
31 public class Demo01 {
32 public static void main(String[] args) {
33 //需求: 把数组元素按照[1, 2, 3, 4, 5]的格式进行输出.
34
35 //1. 定义数组, 记录元素.
36 int[] arr = {1, 2, 3, 4, 5};
37
38 //2. 按照格式进行输出.
39 //方式一: 面向过程编程思想, 即: 每个动作都亲力亲为.
40 System.out.print("[");
41 for (int i = 0; i < arr.length; i++) {
42 if (i == arr.length - 1)
43 System.out.println(arr[i] + "]");
44 else
45 System.out.print(arr[i] + ", ");
46 }
47 System.out.println("----------------------");
48
49
50 //方式二: 面向对象编程思想, 即: 我们只要找对 对象即可, 把事儿交给他/她/它做.
51 System.out.println(Arrays.toString(arr));
52
53 }
54 }

1 package com.it.demo01_oop;
2
3 import java.util.Scanner;
4
5 /*
6 案例: 演示学生类的定义和使用.
7
8 铺垫知识:
9 1. Java语言是用来描述现实世界事物, 最基本的单位是: 类.
10 2. 类就是 属性和行为 的集合, 是一个抽象的概念, 看不见, 也摸不着.
11 属性:
12 指的就是事物的外在特征(名词), 在Java中叫: 成员变量, 字段.
13
14 成员变量:
15 和以前定义变量的格式一样, 只不过写在类中方法外, 且成员变量有默认值.
16
17 行为:
18 指的就是事物能够做什么(动词), 在Java中叫: 成员方法
19
20 成员方法:
21 和以前定义方法格式一样, 只不过先不要写 static
22 3. 对象是类的具体体现, 实现, 能看的见, 也能摸得着.
23 4. 类的定义格式:
24 public class 类名 {
25 //属性
26
27 //行为
28 }
29 5. 类的调用格式, 即: 如何使用类中的成员
30 步骤1: 创建该类的对象.
31 类名 对象名 = new 类名();
32 步骤2: 通过 对象名. 的形式调用类中的成员.
33 对象名.成员变量 //获取该成员变量的值.
34 对象名.成员变量 = 值 //获取指定成员变量的值.
35 对象名.成员方法() //调用指定的成员方法
36
37 */
38 public class Demo02 {
39 public static void main(String[] args) {
40 //需求: 调用Student类中的成员.
41 //1. 创建学生类的对象.
42 Student s = new Student();
43
44 //2. 打印属性值.
45 System.out.println(s.name); //null
46 System.out.println(s.age); //0
47 System.out.println("---------------------");
48
49 //3. 设置属性值.
50 s.name = "刘亦菲";
51 s.age = 33;
52
53 //4. 打印属性值.
54 System.out.println(s.name); //刘亦菲
55 System.out.println(s.age); //33
56
57 //5. 调用成员方法.
58 s.study();
59 }
60 }

package cn.it.demo01;
/*
* 类的方式,描述现实中的事物 小汽车
*
* 小汽车 属性和功能
* 属性: 颜色 轮胎个数 变量定义
* 功能: 跑 方法
*
* 属性和方法,都属于类的成员
*
* 属性, 成员变量
* 方法, 成员方法
*/
public class Car {
//定义Car类的属性

//定义颜色属性  
String color ;  
//定义轮胎个数

int count ;

//定义跑的功能  
public void run(){  
    System.out.println("小汽车在跑 ..."+color+"..."+count);  
}

}

package cn.it.demo01;
/*
* 测试,自定义的类Car
* 创建出Car类的变量
* 变量,调用属性,成员变量
* 变量,调用方法
*/
public class CarTest {

public static void main(String\[\] args) {  
    //创建出Car类的变量 , 创建出Car类的对象,小汽车真的有了  
    Car c = new Car();  
    //对象.调用类中的属性和方法  
    c.color = "无色";  
    c.count = 5 ;

    c.run();  
}

}

1 package com.it.demo02_phone;
2
3 //自定义的手机类.
4 public class Phone {
5 //属性: 品牌(brand), 价格(price), 颜色(color)
6 String brand; //品牌
7 int price; //价格
8 String color; //颜色
9
10 // 行为: 打电话(call), 发短信(sendMessage)
11 public void call(String name) {
12 System.out.println("给" + name + "打电话!");
13 }
14
15 //发短信(sendMessage)
16 public void sendMessage(String name) {
17 System.out.println("给" + name + "发短信!");
18 }
19
20 }
21
22 package com.it.demo02_phone;
23
24 /*
25 案例: 演示手机类的定义和使用.
26
27 需求:
28 1.定义手机类Phone.
29 属性: 品牌(brand), 价格(price), 颜色(color)
30 行为: 打电话(call), 发短信(sendMessage)
31 2.创建测试类PhoneTest, 在类中定义main方法, 并访问手机类(Phone类)中的成员.
32
33 PhoneTest: 手机类的测试类.3
34
35 Phone: 具体的手机类.
36 */
37 public class PhoneDemo {
38 public static void main(String[] args) {
39 //需求: 访问Phone类中的成员.
40 //1. 创建Phone类的对象.
41 Phone p = new Phone();
42 //2. 打印属性值.
43 System.out.println(p.brand);
44 System.out.println(p.price);
45 System.out.println(p.color);
46 System.out.println("---------------------------");
47
48 //3. 设置属性值.
49 p.brand = "华为P30";
50 p.price = 5999;
51 p.color = "土豪金";
52
53 //4. 打印属性值.
54 System.out.println(p.brand);
55 System.out.println(p.price);
56 System.out.println(p.color);
57
58 //5. 调用成员方法.
59 p.call("红红");
60 p.sendMessage("红红");
61 }
62 }
63
64
65 package com.it.demo02_phone;
66
67 //案例: 两个对象的内存图
68 public class PhoneDemo02 {
69 public static void main(String[] args) {
70 //1. 创建手机类的对象.
71 Phone p = new Phone();
72 //2. 设置成员变量值.
73 p.brand = "华为";
74 p.price = 6666;
75 p.color = "黑色";
76 //3. 打印成员变量.
77 System.out.println(p.brand + "--" + p.price + "--" + p.color);
78 //4. 调用成员方法.
79 p.call("李四");
80 p.sendMessage("李四");
81
82 Phone p2 = new Phone();
83 p2.brand = "小米";
84 p2.price = 3333;
85 p2.color = "白色";
86 System.out.println(p2.brand + "--" + p2.price + "--" + p2.color);
87 p2.call("张三");
88 p2.sendMessage("张三");
89 }
90 }
91
92 package com.it.demo02_phone;
93
94 //案例: 演示两个对象指向同一个地址的内存图.
95 public class PhoneDemo03 {
96 public static void main(String[] args) {
97 //1. 创建手机类的对象.
98 Phone p = new Phone();
99 //2. 设置成员变量值.
100 p.brand = "华为";
101 p.price = 6666;
102 p.color = "黑色";
103 //3. 打印成员变量.
104 System.out.println(p.brand + "--" + p.price + "--" + p.color); //华为, 6666, 黑色
105 //4. 调用成员方法.
106 p.call("李四");
107 p.sendMessage("李四");
108
109 Phone p2 = p;
110 p2.brand = "小米";
111 p2.price = 3333;
112 p2.color = "白色";
113 System.out.println(p.brand + "--" + p.price + "--" + p.color); //小米, 3333, 白色
114 System.out.println(p2.brand + "--" + p2.price + "--" + p2.color); //小米, 3333, 白色
115 p2.call("张三");
116 p2.sendMessage("张三");
117 }
118 }

1 package com.it.demo03_variable;
2
3 /*
4 案例: 演示成员变量和局部变量的区别.
5
6 它们的区别有以下4点:
7 1. 定义位置不同.
8 成员变量: 定义在类中, 方法外的变量.
9 局部变量: 定义在方法中, 或者方法形参上的变量.
10 2. 在内存中存储位置不同.
11 成员变量: 存储在堆内存.
12 局部变量: 存储在栈内存.
13 3. 生命周期不同.
14 成员变量: 随着对象的创建而存在, 随着对象的消失而消失.
15 局部变量: 随着方法的调用而存在, 随着方法的调用完毕而消失.
16 4. 初始化值不同.
17 成员变量: 有默认值.
18 局部变量: 没有默认值, 必须先声明, 后赋值, 然后才能使用.
19 */
20 public class Demo01 {
21 public static void main(String[] args) {
22 //需求: 调用Student#show(), 等价于: 调用Student类中的show()方法
23 //1. 创建Student类的对象.
24 Student s = new Student();
25 //2. 调用指定的成员方法
26 s.show();
27 }
28 }
29
30
31 package com.it.demo03_variable;
32
33 //自定义的学生类
34 public class Student {
35 //成员变量, 属性
36 int a = 20;
37
38 //成员方法, 行为
39 public void show() {
40 //局部变量
41 int b = 10;
42
43 System.out.println(a); //20
44 System.out.println(b); //10
45 }
46 }

1 package cn.it.demo02;
2
3 public class Car {
4 String color;
5 int count ;
6 public void run(){
7
8 int x=1;
9 /*for(int i = 0 ; i < 4 ;i++){
10
11 }*/
12 System.out.println("小汽车在跑 …"+color+"…"+count);
13 System.out.println(x);
14 }
15 }
16
17
18
19 package cn.it.demo02;
20 /*
21 * 成员变量和局部变量的区别
22 *
23 * 1. 定义位置上的区别
24 * 成员变量,定义在类中,方法外
25 * 局部变量,方法内,语句内
26 *
27 * 2. 作用域不同
28 * 成员变量,作用范围是整个类
29 * 局部变量,方法内,语句内
30 *
31 * 3. 默认值不同
32 * 成员变量,有自己的默认值
33 * 局部变量,没有默认值,不赋值不能使用
34 *
35 * 4. 内存位置不同
36 * 成员变量,跟随对象进入堆内存存储
37 * 局部变量,跟随自己的方法,进入栈内存
38 *
39 * 5. 生命周期不同
40 * 成员变量,跟随对象,在堆中存储,内存等待JVM清理 , 生命相对较长
41 * 局部变量,跟随方法,方法出栈 生命相对较短
42 */
43 public class CarTest {
44 public static void main(String[] args) {
45 Car c = new Car();
46 c.run();
47 }
48 }

1 package cn.it.demo03;
2
3 public class Person {
4 String name ;
5 }
6
7 package cn.it.demo03;
8 /*
9 * 方法的参数类型,是基本数据类型,引用数据类型
10 */
11 public class TestPerson {
12 public static void main(String[] args) {
13 int a = 1;
14 function(a);
15 System.out.println(a);
16
17 Person p = new Person();
18 p.name = "张三";
19 System.out.println(p.name);
20
21 function(p);
22
23 System.out.println(p.name);
24 }
25 /*
26 * 定义方法,参数类型是引用数据类型
27 * 参数是Person类型
28 * p接受的是一个内存的地址
29 * main 中的变量p
30 * function 中的变量p 保存的地址是一样的
31 */
32 public static void function(Person p){
33 p.name = "李四";
34 }
35
36 /*
37 * 定义方法,参数类型是基本数据类型
38 */
39 public static void function(int a){
40 a+=5;
41 }
42 }

1 package com.it.demo04_private;
2
3 //自定义学生类
4 public class Student {
5 //属性
6 String name;
7 private int age;
8
9 //对外提供一个公共的访问方式, 来操作age变量.
10 //提供方法, 设置age的值.
11 public void setAge(int a) {
12 if (a >= 0 && a <= 250) {
13 //走到这里, 说明年龄合法.
14 age = a;
15 }
16 }
17 }package com.it.demo04_private;
18
19 /*
20 案例: 演示private关键字的用法.
21
22 private简介:
23 为什么要学习private?
24 因为目前我们代码中的成员变量, 外界是可以直接访问的, 这样的话, 用户就有可能给录入一些非法值,
25 造成安全隐患, 所以我们要对 成员变量进行一层封装, 不让外界直接访问了.
26 //大白话理解: 银行的钱用户是无法直接访问的, 要通过柜台小姐姐或者ATM自动存取款机来操作.
27 概述:
28 它是一个关键字, 表示"私有"的意思, 也是访问权限修饰符的一种,
29 被它修饰的内容, 只能在本类中直接使用.
30
31 应用场景:
32 1.在实际开发中, 成员变量基本上都是用private关键字来修饰的.
33 2.如果明确知道类中的某些内容不想被外界直接访问, 都可以通过private来修饰.
34
35 细节:
36 因为被private修饰的内容, 只能在本类中直接访问, 外界如果想使用这些私有成员, 需要通过特定方式.
37 即: 我们可以在类中定义两个方法, 一个是setXxx(), 用来设置属性值, 一个getXxx(), 用来获取属性值.
38
39 */
40 public class StudentTest {
41 public static void main(String[] args) {
42 //1. 创建对象.
43 Student s = new Student();
44 //2. 给属性赋值.
45 s.name = "刘亦菲";
46 //s.age = -33; //私有成员外界无法直接访问.
47 s.setAge(33);
48 //3. 打印属性值.
49 System.out.println(s.name + "…" + s.getAge());
50 //4. 调用成员方法.
51 s.study();
52 }
53 }

package cn.it.demo04;
/*
* 描述现实生活中的人的事物
* 属性: 姓名 年龄
* 功能: 说话
*
* 出现安全问题: age问题,可能出现赋值为负数的情况
* 负数不会导致程序问题,违反生活中的真实情况
*
* 提高安全问题: 让外面的类,不允许直接调用我的成员变量
* 新的关键字 private 私有 属于成员修饰符,不能修饰局部变量
* 被private修饰的成员,只能在自己的本类中被使用
*
* 对私有变量,提供公共的访问方式: 方法
*/
public class Person {
//人的姓名,成员变量
String name;
//人的年龄,成员变量
private int age ;

//变量age被私有,提供方法,让外面的类使用  
//定义方法,对age变量进行赋值,方法名字,必须set开头  
public void setAge(int a){  
    //对变量参数a进行范围的限制  
    if(a<0 || a > 200){  
        //如果a超过范围,手动将age赋值为20  
        age = 20;  
    }else{  
    //如果a没有超过范围,直接对age赋值  
    age = a;  
    }  
}

//定义方法,对变量age获取值使用,方法名字get  
public int getAge(){  
    return age;  
}

//定义人的说话功能,方法中,要求说出自己的姓名和年龄  
public void speak(){  
    System.out.println(name+"..."+age);  
}  

}
package cn.it.demo04;
/*
* 定义好的Person类进行测试
* 创建对象,对象调用属性和方法
*/
public class PersonTest {

public static void main(String\[\] args) {  
    //创建Person类的对象  new  
    Person p = new Person();  
    //对成员变量赋值  
    //p.age = -200;  
    //对成员变量age赋值,只能调用Set方法赋值  
    p.setAge(50);

    p.name = "张三";  
    //调用类中方法  
    p.speak();

    //输出成员变量age值,必须调用get方法  
    System.out.println(p.getAge());  
}

}

1 package com.it.demo05_student;
2
3 //自定义的学生类, 像这种用来描述实体的类也叫: 实体类, 或者JavaBean类, POJO类.
4 public class Student {
5 //属性: 姓名和年龄
6 private String name; //姓名
7 private int age; //年龄
8
9 //对外提供getXxx()和setXxx(), 让用户来操作name和age属性.
10 //获取姓名
11 public String getName() {
12 return name;
13 }
14 //设置姓名
15 public void setName(String n) {
16 //这里可以判断n(传入的姓名)是否合法, 但是我们不做
17 name = n;
18 }
19
20 //获取年龄
21 public int getAge(){
22 return age;
23 }
24
25 //设置年龄
26 public void setAge(int a) {
27 //这里可以判断a(传入的年龄)是否合法, 但是我们不做
28 age = a;
29 }
30
31 //行为: 学习, 吃饭.
32 public void study() {
33 System.out.println("键盘敲烂, 月薪过万!");
34 }
35
36 public void eat() {
37 System.out.println("学生吃牛肉!");
38 }
39 }
40
41 package com.it.demo05_student;
42
43 /*
44 案例: 演示加入private关键字后的 "标准代码".
45
46 需求:
47 1.定义一个标准的学生类Student, 属性: 姓名和年龄, 行为: 学习, 吃饭.
48 2.在测试类中创建学生类的对象, 然后访问类中的成员.
49
50 StudentDemo类: 测试类.
51 */
52 public class StudentDemo {
53 public static void main(String[] args) {
54 //1. 创建对象.
55 Student s = new Student();
56 //2. 设置属性值.
57 //s.name = "刘亦菲"; //private修饰的内容, 外界无法直接访问.
58 s.setName("刘亦菲");
59 /*
60 这里的-33是我们自己手动传入的, 实际开发中, 没有这种情况, 因为数据从前端传过来的,
61 当数据从前端传过来的时候, 已经经过了校验, 换言之, 我们在后台获取到的数据已经是合法的了,
62 如果再做校验属于二次校验, 可以做, 也可以不做, 一般不做, 具体看需求.
63 */
64 //s.setAge(-33);
65 s.setAge(33);
66 //3. 打印属性值.
67 System.out.println(s.getName() + "…" + s.getAge());
68 //4. 调用成员方法.
69 s.study();
70 s.eat();
71 }
72 }

package com.it.demo06_this;

//自定义的学生类, 像这种用来描述实体的类也叫: 实体类, 或者JavaBean类, POJO类.
public class Student {
//属性: 姓名和年龄
private String name; //姓名
private int age; //年龄

//对外提供getXxx()和setXxx(), 让用户来操作name和age属性.  
//获取姓名  
public String getName() {  
    return name;  
}

//设置姓名  
public void setName(String name) {  
    this.name = name;  
}

//获取年龄  
public int getAge(){  
    return age;  
}

//设置年龄  
public void setAge(int age) {  
    this.age = age;  
}

//行为: 学习, 吃饭.  
public void study() {  
    System.out.println("键盘敲烂, 月薪过万!");  
}

public void eat() {  
    System.out.println("学生吃牛肉!");  
}  

}
package com.it.demo06_this;

/*
案例: 演示this关键字.

封装简介:  
    概述:  
        封装就是隐藏对象的属性和实现细节, 仅对外提供一个公共的访问方式.  
        怎么隐藏?  
            可以通过private关键字实现.  
        公共的访问方式是什么?  
            getXxx(), setXxx()  
    原则:  
        1. 把不需要对外暴漏的内容都封装起来.  
        2. 把成员变量全部私有化(封装起来).  
        //大白话翻译: 成员变量私有化(private修饰), 其他用public修饰.

    好处:  
        1. 提高了代码的安全性.        由private保证.  
        2. 提高了代码的复用性.        由方法保证.

this关键字简介  
    概述:  
        它是一个关键字, 代表本类当前对象的引用.  
        //大白话: 谁调用, this就代表谁.  
    作用:  
        用来解决局部变量和成员变量重名问题的.

    补充: 使用变量的原则  
        使用变量遵循就近原则, 如果局部位置有, 就使用, 没有就去本类的成员位置找, 有就是使用.  
        没有就报错.      //先这么记忆, 不严谨, 因为本类找不到, 还回去父类找.  

*/
public class StudentDemo {
public static void main(String[] args) {
//需求1: 调用Teacher#show(), 演示使用变量的原则.
//method01();

    //需求2: 加入this后的, 标准的Student类的代码编写和调用.  
    //1. 创建对象.  
    Student s = new Student();  
    //2. 设置属性值.  
    //s.name = "刘亦菲";     //private修饰的内容, 外界无法直接访问.  
    s.setName("刘亦菲");  
    s.setAge(33);  
    //3. 打印属性值.  
    System.out.println(s.getName() + "..." + s.getAge());  
    //4. 调用成员方法.  
    s.study();  
    s.eat();

}

public static void method01() {  
    Teacher t = new Teacher();  
    t.a = 100;  
    t.show();  
}  

}

1 package cn.it.demo05;
2
3 /*
4 * 类描述人:
5 * 属性: 姓名和年龄
6 * 方法: 说话
7 *
8 * 私有化所有的属性 (成员变量) ,必须写对应的get/set方法
9 * 凡是自定义的类,自定义成员变量,应该私有化,提供get/set
10 *
11 * this关键字:
12 * 区分成员变量和局部变量同名情况
13 * 方法中,方位成员变量,写this.
14 */
15 public class Person {
16 private String name;
17 private int age;
18
19 // set方法,变量name,age赋值
20 public void setAge(int age) {
21 this.age = age;
22 }
23
24 public void setName(String name) {
25 this.name = name;
26 }
27
28 // get方法,变量name,age获取值
29 public int getAge() {
30 return age;
31 }
32
33 public String getName() {
34 return name;
35 }
36
37 public void speak() {
38 String name = "哈哈";
39 int age = 16;
40
41 System.out.println("人在说话 " + this.name + "…" + this.age);
42 }
43 }
44
45
46 package cn.it.demo05;
47
48 public class PersonTest {
49 public static void main(String[] args) {
50 Person p = new Person();
51 //调用set方法,对成员变量赋值
52 p.setAge(18);
53 p.setName("旺财");
54 p.speak();
55
56
57 //调用get方法,获取成员变量的值
58 // System.out.println(p.getName());
59 // System.out.println(p.getAge());
60 }
61 }

package cn.it.demo06;

public class Person {
private int age;

public void setAge(int age){  
    this.age = age;  
}

public int getAge(){  
    return age;  
}

/\*  
 \* 定义方法: 比较是否是同龄人,是就返回true,不是就返回false  
 \* 谁和谁比呀,我自己和别人比  
 \* 方法的返回值: true false  
 \* 方法参数: 别人  
 \*/  
public boolean compare(Person p){  
    //自己和别人比年龄,自己是谁 this和p  
    return this.age == p.age;  
}  

}

package cn.it.demo06;

public class PersonTest {
public static void main(String[] args) {
//测试Person类中的年龄比较功能
//创建出2个Person对象
Person p1 = new Person();
Person p2 = new Person();

    p1.setAge(15);  
    p2.setAge(16);

    //p1对象调用自己的方法compare传递p2对象  
    boolean b = p1.compare(p2);  
    System.out.println(b);  
}  

}

1 package com.it.demo07_constructor;
2
3 //自定义的学生类
4 public class Student {
5 //属性
6 private String name;
7 private int age;
8
9 //系统默认加的空参.
10 public Student() {
11 System.out.println("我是空参构造方法");
12 }
13
14 //自己给的全参
15 public Student(String name, int age) {
16 System.out.println("我是全参构造方法");
17 this.name = name;
18 this.age = age;
19 }
20 }
21
22 package com.it.demo07_constructor;
23
24 /*
25 案例: 演示构造方法入门.
26
27 构造方法详解:
28 概述:
29 主职 兼职
30 构造方法就是用来快速创建对象的, 捎带着可以给对象的各个属性赋值.
31 注意事项:
32 1. 构造方法名和类名完全一致(包括大小写)
33 2. 构造方法没有返回值的数据类型, 连void都不能写.
34 3. 构造方法没有具体的返回值, 但是可以写return.
35 //return的作用是: 用来结束方法的, 捎带着可以返回具体的值.
36 4. 构造方法可以重载.
37 5. 每个类系统都会默认加一个: 空参构造, 如果你写了构造方法(不管是否是空参), 系统就不给了.
38 6. 推荐做法: 无论是否使用, 类中都要提供两个构造, 即: 空参构造, 全参构造.
39 格式:
40 public 类名(数据类型 参数名1, 数据类型 参数名2) {
41 //这里可以给该类中对应的成员变量赋值.
42 }
43
44 创建对象的格式:
45 类名 对象名 = new 构造方法名(值1, 值2, 值3);
46 */
47 public class StudentDemo {
48 public static void main(String[] args) {
49 //创建Student类的对象
50 Student s = new Student();
51 //s.setName("刘亦菲");
52 //s.setAge(33);
53 System.out.println("----------------------");
54
55 Student s2 = new Student("刘亦菲", 33);
56 }
57 }

1 package com.it.demo02_quickstart;
2
3 //自定义的人类, 表示父类.
4 public class Person {
5 //属性
6 private String name; //姓名
7 private int age; //年龄
8
9 //构造方法
10 public Person() {
11 }
12
13 public Person(String name, int age) {
14 this.name = name;
15 this.age = age;
16 }
17
18 //getXxx(), setXxx()
19 public String getName() {
20 return name;
21 }
22
23 public void setName(String name) {
24 this.name = name;
25 }
26
27 public int getAge() {
28 return age;
29 }
30
31 public void setAge(int age) {
32 this.age = age;
33 }
34
35 //行为
36 public void eat() {
37 System.out.println("人要吃饭!");
38 }
39
40 public void sleep() {
41 System.out.println("人要睡觉!");
42 }
43
44 public void smoking() {
45 System.out.println("人要抽烟!");
46 }
47 }
48
49
50 package com.it.demo02_quickstart;
51
52 //自定义的学生类, 继承人类.
53 public class Student extends Person{
54 //行为: 学习
55 public void study() {
56 System.out.println("学生要学习!");
57 }
58 }
59
60
61 package com.it.demo02_quickstart;
62
63 //自定义的老师类, 继承人类.
64 public class Teacher extends Person{
65 //构造方法, 子类的空参访问父类的空参, 子类的全参访问父类的全参.
66
67 //行为: 教课
68 public void teach() {
69 System.out.println("老师要教课!");
70 }
71 }

package com.it.demo03_father;

//自定义的爷爷类
public class GrandFather {
public void grandFatherSay() {
System.out.println("爷爷都是从孙子过来的");
}
}

package com.it.demo03_father;

//自定义的爸爸类
public class Father extends GrandFather{
public void fatherSay() {
System.out.println("爸爸都是从儿子过来的!");
}
}

package com.it.demo03_father;

//自定义的儿子类.

//public class Son extends Father, GrandFather{ //报错: Java中类与类之间只能单继承, 不能多继承.
public class Son extends Father{
}

package com.it.demo03_father;

/*
案例: 演示Java中类与类之间的继承特点.

需求:  
    1.定义GrandFather类, 该类有一个grandFatherSay()方法, 该方法打印一句话爷爷都是从孙子过来的.  
    2.定义Father类, 该类有一个fatherSay()方法, 该方法打印一句话爸爸都是从儿子过来的.  
    3.定义Son类, 分别先继承自GrandFather类和Father类, 此时发现, 上述的两个方法只能同时调用一个.  
    4.如果想让Son类的对象, 同时能调用上述的两个方法, 则可以这样做:  
     Son类继承自Father类, Father类继承自GrandFather类.

结论(记忆):   Java中类与类之间的继承关系特点如下:  
    1. Java中类与类之间只能单继承, 不能多继承.          //大白话翻译: 一个人只能有一个亲爹.  
    2. Java中支持多层继承.                              //大白话翻译: 一个人可以有一个亲爹, 还可以有一个亲爷爷.  
    3. 所有的类都直接或者间接继承自Object类, 换言之, Object类是所有类的父类.

快捷键:  
    查看继承关系树:  ctrl + 字母H  

*/
public class Demo01 {
public static void main(String[] args) {
Son s = new Son();
s.fatherSay(); //从Father类继承的.
s.grandFatherSay(); //从GrandFather类继承的.
}
}

package cn.it.demo01;
/*
* 定义员工类
* 属性和方法
* 属性成员变量, 姓名
* 成员方法, 工作
*/
public class Employee {
String name;

 public void work(){  
     System.out.println("员工在工作");  
 }  

}

package cn.it.demo01;
/*
* 定义研发部员工
* 属于员工中的一种
* 研发员工继承员工类
*
* 关键字 extends
* 子类是Develop, 父类是Employee
* 子类自动拥有父类中可以继承的属性和方法
*
* 子类中,可以直接调用父类的成员
*/
public class Develop extends Employee{
//在子类中,可以定义方法
public void print(){
System.out.println(name);
}
}
package cn.it.demo01;
/*
* 定义维护员工类
* 属于员工的一种, 继承员工类
*/
public class WeiHu extends Employee{
public void print(){
System.out.println(name);
}
}

1 package com.it.demo03_variable;
2
3 //自定义的父类
4 public class Father {
5 //成员变量
6 int age = 30;
7 }
8
9
10 package com.it.demo03_variable;
11
12 //自定义的子类
13 public class Son extends Father {
14 //成员变量
15 int age = 20;
16
17 //成员方法
18 public void show() {
19 //局部变量
20 int age = 10;
21 System.out.println(age); //10
22 System.out.println(this.age); //20
23 System.out.println(super.age); //30
24 }
25 }
26
27 package com.it.demo03_variable;
28
29 /*
30 案例: 演示继承关系中的成员变量的访问特点:
31
32 需求:
33 1.定义Father类, 在该类的成员位置定义变量: int age = 30;
34 2.定义Son类, 让它继承Father类, 并在该类的成员位置定义变量: int age = 20;
35 3.在测试类FatherTest的main方法中, 定义变量: int age = 10;
36 4.通过输出语句, 直接打印age变量的值, 并查看程序的运行结果.
37
38 结论(记忆):
39 1. 使用变量遵循就近原则, 局部位置有使用, 没有就去本类的成员位置找,
40 有就使用, 没有就去父类的成员位置找, 有就使用, 没有就报错. //这里不考虑父类的父类这种情况, 会会一直找, 直到找到Object类.
41 2. 本类的局部变量, 本类的成员变量, 父类的成员变量重名时, 如何解决?
42 本类的局部变量: 直接写.
43 本类的成员变量: this.成员变量名
44 父类的成员变量: super.成员变量名
45
46
47 从本案例开始, 我们来研究继承关系中的成员特点:
48 成员变量的特点:
49 1. 就近原则.
50 2. 解决重名. super, this
51 构造方法的特点:
52
53 成员方法的特点:
54 */
55 public class Demo01 {
56 public static void main(String[] args) {
57 //需求: 调用Son#show()
58 Son s = new Son();
59 s.show();
60 }
61 }

package com.it.demo04_constructor;

//自定义的父类
public class Father {
public Father() {
//super(); //Father类的父类, Object类的.
System.out.println("Father类的 空参 构造");
}

public Father(String name) {  
    //super();        //Father类的父类, Object类的.  
    System.out.println("Father类的 带参 构造");  
}  

}

package com.it.demo04_constructor;

//自定义的子类
public class Son extends Father{
/*public Son() {
//super("abc"); //用来初始化Father类的成员的
this("abc");
System.out.println("Son类的 空参 构造");
} //这行代码走完,意味着Son对象创建成功.

public Son(String name) {  
  // super(name);  //用来初始化Father类的成员的  
    System.out.println("Son类的 带参 构造");  
}\*/

//实际开发写法: 子类的空参访问父类的空参, 子类的全参访问父类的全参.  
public Son() {  
    super();  
    System.out.println("Son类的 空参 构造");  
}

public Son(String name) {  
   super(name);  
    System.out.println("Son类的 带参 构造");  
}  

}

package com.it.demo04_constructor;

/*
案例: 演示继承关系中 构造方法的访问特点..

需求:  
    1.定义父类Father, 并在空参构造中打印一句话: Father空参构造.  
    2.定义子类Son, 并在空参构造中打印一句话: Son空参构造.  
    3.在FatherTest测试类的main方法中, 创建Son类的对象, 并查看程序的执行结果.  
    4.分别修改Father类和Son类的代码, 添加带参构造, 并观察程序的执行结果.

结论(记忆:):  
    1. 子类的所有构造方法的第一行默认都有一个: super() 访问父类的空参构造.  
        问题一: 为什么这样设计?  
            用于子类对象访问父类数据前, 对父类数据进行初始化.  
            //大白话: 子类对象一旦创建成功, 就能直接使用父类的成员了, 因为父类成员在子类成员之前就已经初始化了.  
        问题二: 为什么默认访问的是空参, 而不是带参?  
            因为所有的类都直接或者间接继承自Object类, Object类是所有类的父类.  
            它里边只有一个空参构造.  
        问题三: 父类没有空参构造怎么办?  
            方案一: 通过 super()访问父类的带参构造.  
            方案二: 通过 this()访问本类的其他构造.  
    2. 实际开发写法: 子类的空参访问父类的空参, 子类的全参访问父类的全参.

*/
public class Demo01 {
public static void main(String[] args) {
//需求: 创建Son类的对象.
Son s = new Son();
System.out.println("---------");

    Son s2 = new Son("abc");  
}  

}

package com.it.demo05_method;

//自定义的Father类
public class Father {
public void method() {
System.out.println("Father method()方法");
}

public void show() {  
    System.out.println("Father show()方法");  
}  

}

package com.it.demo05_method;

//自定义的子类
public class Son extends Father{
public void method() {
super.method(); //调用父类的method()方法
System.out.println("Son method()方法");
}

/* public void show() {
System.out.println("Son show()方法");
}*/
}

package com.it.demo05_method;

/*
案例: 演示继承关系中的成员方法访问特点.

需求:  
    1.定义Father类, 并在类中定义method()方法和show()方法.  
    2.定义Son类, 并在类中定义method()方法和show()方法.  
    3.在FatherTest测试类中, 创建Son类的对象, 并调用类中的成员方法.  
    4.注释子类中的method()方法或者show()方法, 并观察程序的执行结果.

结论(记忆):  
    调用成员方法时, 也遵循就近原则, 本类中有, 就直接调用, 本类中没有, 就去父类中查找, 有就使用, 没有就报错.

*/
public class Demo01 {
public static void main(String[] args) {
Son s = new Son();
s.show();
System.out.println("-----------");
s.method();
}
}

package com.it.demo06_override;

//自定义的手机类
public class Phone {
public void call(String name) {
System.out.println("给" + name + "打电话");
}

public void show() {  
    System.out.println("show方法");  
}  

}

package com.it.demo06_override;

//自定义的新式手机类
public class NewPhone extends Phone{
@Override
public void call(String name) {
super.call(name); //调用Phone#call()方法
System.out.println("新式手机会播放彩铃…");
}

@Override  
public void show() {     //报错: 父类中私有的方法不能被重写  
    System.out.println("show方法");  
}

/\*private void show() {     //报错: 父类中私有的方法不能被重写  
    System.out.println("show方法");  
}\*/  

}

package com.it.demo06_override;

//自定义的手机类
public class Phone {
public void call(String name) {
System.out.println("给" + name + "打电话");
}

public void show() {  
    System.out.println("show方法");  
}  

}

package com.it.demo06_override;

/*
案例: 演示方法重写.

需求:  
    1.定义Phone类, 并在类中定义call(String name)方法.  
    2.定义NewPhone类, 继承Phone类, 然后重写call(String name)方法.  
    3.在PhoneTest测试类中, 分别创建两个类的对象, 然后调用call()方法, 观察程序执行结果.

方法重写简介:  
    概述:  
        子类中出现和父类一模一样的方法时, 称为方法重写, 方法重写要求子父类的方法的返回值类型也必须一致.  
    应用场景:  
        当子类需要沿袭父类的功能, 但是功能主体又有自己独有需求的时候, 就可以考虑使用方法重写来实现了.  
    注意事项:  
        1.子类重写父类方法时, 方法声明上要用@Override注解来修饰.  
        2.父类中私有的方法不能被重写.  
        3.子类重写父类方法时, 访问权限不能更低.  
            访问权限修饰符的访问级别, 从小到大分别是:  
                private < 默认 < protected < public  

*/
public class Demo01 {
public static void main(String[] args) {
//测试Phone#call()
Phone p = new Phone();
p.call("刘亦菲");
System.out.println("-----------------");

    //测试NewPhoenix#call()方法  
    NewPhone np = new NewPhone();  
    np.call("赵丽颖");  
}  

}

package com.it.demo07_exercise_person;

//自定义父类, 人类.
public class Person {
//属性, 姓名, 年龄
private String name; //赵丽颖"
private int age; //31

//构造方法  
public Person() {  
}

public Person(String name, int age) {   //"赵丽颖", 31  
    this.name = name;  
    this.age = age;  
}

//getXxxx(), setXxx()  
public String getName() {  
    return name;  
}

public void setName(String name) {  
    this.name = name;  
}

public int getAge() {  
    return age;  
}

public void setAge(int age) {  
    this.age = age;  
}

//行为: 吃饭.  
public void eat() {  
    System.out.println("人要吃饭!");  
}  

}

package com.it.demo07_exercise_person;

//自定义的学生类, 继承人类
public class Student extends Person{
//构造方法: 空参访问空参, 全参访问全参.
public Student() {
}

public Student(String name, int age) {   //"赵丽颖", 31  
    super(name, age);       //"赵丽颖", 31  
}

//行为  
//定义学习的方法  
public void study() {  
    System.out.println("学生要好好学习");  
}

@Override  
public void eat() {  
    System.out.println("学生吃牛肉!");  
}  

}

package com.it.demo07_exercise_person;

//自定义的老师类
public class Teacher extends Person {
//变量, 目前没有.

//构造方法: 子类空参访问父类空参, 子类全参访问父类全参.  
public Teacher() {  
}

public Teacher(String name, int age) {  
    super(name, age);  
}

//行为  
// 定义teach()方法.  
public void teach() {  
    System.out.println("老师要教课!");  
}

//重写Person#eat()  
@Override  
public void eat() {  
    System.out.println("老师喝牛肉汤!");  
}  

}

package com.it.demo07_exercise_person;

/*
案例: 继承版的人类案例.

需求:  
    1.已知老师类Teacher, 属性有姓名和年龄, 行为有teach()  
    2.已知学生类Student, 属性有姓名和年龄, 行为有study()  
    3.他们都要吃饭, 不同的是学生吃牛肉, 老师喝牛肉汤.  
    4.分析上述的需求, 并通过代码实现.  
    5.在PersonTest类的main方法中, 分别创建老师类和学生类的对象, 然后访问其成员.

 分析:  
    1. 抽取父类 Person.  
        属性:  
            姓名, 年龄  
        行为:  
            吃饭eat()  
    2. 定义子类Teacher, 继承Person  
        行为:  
            定义teach()方法.  
            重写Person#eat()  
    3. 定义子类Student, 继承Person  
        行为:  
             定义study()方法.  
            重写Person#eat()方法.  

*/
public class PersonTest {
public static void main(String[] args) {
//需求: 测试学生类.
//测试空参
Student s1 = new Student(); //学生是学生
//这些常用都是从Person类中继承过来的.
s1.setName("刘亦菲");
s1.setAge(33);
System.out.println(s1.getName() + "…" + s1.getAge());
s1.eat(); //重写Person#eat()方法
s1.study(); //Student类的独有功能.
System.out.println("-------------------------");

    //测试全参  
    Student s2 = new Student("赵丽颖", 31);  
    System.out.println(s2.getName() + "..." + s2.getAge());  
    s2.eat();  
    s2.study();

    //需求: 测试老师类, 代码留给你写了.  
}  

}

package com.it.demo08_quickstart;

//自定义的动物类
public class Animal {
public void eat() {
System.out.println("动物要吃饭!");
}
}

package com.it.demo08_quickstart;

//自定义的猫类, 继承动物类
public class Cat extends Animal{
//重写Animal#eat()
@Override
public void eat() {
System.out.println("猫吃鱼!…");
}
}

package com.it.demo08_quickstart;

/*
案例: 演示多态入门.

需求:  
    1.定义动物类Animal, 并在类中定义一个成员方法: eat()  
    2.定义猫类Cat, 继承Animal类, 并重写eat()方法.  
    3.在AnimalTest测试类的main方法中, 通过多态的方式创建猫类对象.  
    4.通过猫类对象, 调用eat()方法.

多态简介:  
    概述:  
        指的是同一个对象(事物)在不同时刻表现出来的不同形态, 状态.  
        //例如: 一杯水,  高温: 气态,  常温: 液态,  低温: 固态.  
    前提条件:  
        1. 要有继承关系.  
        2. 要有方法重写.  
        3. 要有父类引用指向子类对象.  

*/
public class AnimalTest {
public static void main(String[] args) {
//1. 通过多态的方式创建猫类对象.
Animal an = new Cat(); //猫是动物.
Cat c = new Cat(); //猫是猫

    //2. 调用eat()方法  
    an.eat();  
    System.out.println("..............");  
    c.eat();  
}  

}

package com.it.demo09_person;

//自定义的人类
public class Person {
int age = 30;

public void eat() {  
    System.out.println("Person eat()");  
}

/* public static void sleep() {
System.out.println("Person sleep()");
}*/
}

package com.it.demo09_person;

//自定义的学生类
public class Student extends Person {
int age = 20;

@Override  
public void eat() {  
    System.out.println("Student eat()");  
}

//自己独有的成员方法  
public void study() {  
    System.out.println("学生要学习!");  
}

/\*public static void sleep() {  
    System.out.println("Student sleep()");  
}\*/  

}

package com.it.demo09_person;

/*
案例: 演示多态中的成员访问特点.

需求:  
    1.定义一个人类Person. 属性为姓名和年龄, 行为是: eat()方法.  
    2.定义Student类, 继承自Person类, 定义age属性及重写eat()方法.  
    3.在PersonTest测试类的main方法中, 创建Student类的对象, 并打印其成员.

结论(记忆):  
    成员变量:   编译看左, 运行看左.  
    成员方法:   编译看左, 运行看右.

    解释:  
        编译看左的意思是: 在程序的编译期间, 会看左边的数据类型有没有这个成员, 有则编译通过, 否则, 编译报错.  
        运行看左(右)的意思是: 在程序的运行期间, 具体用的是左(右)边数据类型中的成员.  
    简单记忆:  
        只有非静态方法是 编译看左, 运行看右, 其他(成员变量, 静态方法)都是编译和运行都看左,  
        原因是因为: 只有非静态方法有方法重写.

 多态的好处和弊端:  
    好处:  
        提高代码的扩展性.  
    弊端:  
        父类引用不能访问子类的特有功能.  

*/
public class Demo01 {
public static void main(String[] args) {
//需求: 演示多态中的成员访问特点.
//1. 通过多态, 创建学生类的对象.
//父类引用 指向 子类对象, 多态写法.
Person p = new Student();
//2. 测试访问成员变量
System.out.println(p.age); //30
//3. 测试访问成员方法
p.eat(); //student eat()

    //p.sleep();

    //这样写会报错, 因为多态的弊端是: 父类引用不能访问子类的特有功能  
    //p.study();  
}  

}

package com.it.demo10_case;

//自定义的父类, 动物类
public class Animal {
public void eat() {
System.out.println("动物要吃!");
}
}

package com.it.demo10_case;

//自定义的猫类
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}

//猫独有的成员方法  
public void catchMouse() {  
    System.out.println("猫会抓老鼠!");  
}  

}

package com.it.demo10_case;

//自定义的父类, 动物类
public class Animal {
public void eat() {
System.out.println("动物要吃!");
}
}

package com.it.demo11_animal;

//父类, 动物类
public class Animal {
//属性, 全部私有
private String name;
private int age;

//构造方法: 空参, 全参  
public Animal() {  
}

public Animal(String name, int age) {  
    this.name = name;  
    this.age = age;  
}

//getXxx(), setXxx()  
public String getName() {  
    return name;  
}

public void setName(String name) {  
    this.name = name;  
}

public int getAge() {  
    return age;  
}

public void setAge(int age) {  
    this.age = age;  
}

//行为  
public void eat() {  
    System.out.println("动物要吃!");  
}  

}

package com.it.demo11_animal;

//猫类
public class Cat extends Animal{
//构造方法: 空参访问空参, 全参访问全参.
public Cat() {
}

public Cat(String name, int age) {  
    super(name, age);  
}

//行为  
//1. 重写Animal#eat()

@Override  
public void eat() {  
    System.out.println("猫吃鱼");  
}

//2. 自身独有的方法catchMouse()  
public void catchMouse() {  
    System.out.println("猫会抓老鼠!");  
}  

}

package com.it.demo11_animal;

//狗类
public class Dog extends Animal{
//构造方法: 空参访问空参, 全参访问全参.
public Dog() {
}

public Dog(String name, int age) {  
    super(name, age);  
}

//行为  
//1. 重写Animal#eat()  
@Override  
public void eat() {  
    System.out.println("狗吃肉");  
}

//2. 自身独有的方法lookHome()  
public void lookHome() {  
    System.out.println("狗会看家!");  
}  

}

package com.it.demo11_animal;

import java.util.Calendar;

/*
多态案例: 动物类案例.

需求:  
    1.已知猫狗都有姓名和年龄, 都要吃饭.  
    2.猫类独有自己的catchMouse()方法, 狗类独有自己的lookHome()方法.  
    3.在AnimalTest测试类的main方法中, 通过多态分别创建猫类, 狗类的对象.  
    4.分别通过猫类对象和狗类对象, 访问对象的成员.

 分析:  
    父类: 动物类 Animal  
        属性: 姓名, 年龄  
        行为: eat()吃饭  
    子类:  
        猫类: Cat  
            行为:  
                1. 重写Animal#eat()  
                2. 自身独有的方法catchMouse()  
         狗类: Dog  
            行为:  
                1. 重写Animal#eat()  
                2. 自身独有的方法lookHome()  

*/
public class AnimalTest {
public static void main(String[] args) {
//需求1: 多态测试猫类
//测试空参
Animal an1 = new Cat();
//设置成员变量值
an1.setName("机器猫");
an1.setAge(16);
//打印成员变量值
System.out.println(an1.getName() + "…" + an1.getAge());
//调用方法
an1.eat(); //猫吃鱼, 因为有方法重写.
//an1.catchMouse(); //报错, 父类应用不能直接使用子类的特有成员.
Cat c1 = (Cat)an1;
c1.catchMouse();
System.out.println("-------------------------");

    //测试全参  
    Animal an2 = new Cat("加菲猫", 13);  
    //打印成员变量值  
    System.out.println(an2.getName() + "..." + an2.getAge());  
    //调用方法  
    an2.eat();             //猫吃鱼, 因为有方法重写.  
    //an2.catchMouse();   //报错, 父类应用不能直接使用子类的特有成员.  
    Cat c2 = (Cat)an2;  
    c2.catchMouse();

    //需求2: 多态测试狗类, 自己写.  
    //测试空参

    //测试全参  
}  

}

package com.it.demo11_animal;

/*
案例: 演示类型转换异常(ClassCastException)

大白话理解:  
    猫不能转成狗.  

*/
public class AnimalTest02 {
public static void main(String[] args) {
Animal an = new Cat(); //动物是猫
Cat c = (Cat)an; //猫是猫
c.catchMouse();
System.out.println("-----------------");

    //会报: 类型转换异常(ClassCastException)  
    //多态  
    an = new Dog();  
    Dog d = (Dog)an;  
    d.lookHome();  
}  

}

package com.it.demo11_animal;

/*
案例: 演示多态在实际开发中的应用场景.

多态在实际开发中的应用场景:  
    父类型可以作为方法的形参类型, 这样可以接受其任意的子类对象,  
    然后调用方法的时候, 根据"编译看左, 运行看右"的原则, 传入什么  
    子类对象, 就调用其对应的方法.  

*/
public class AnimalTest03 {
public static void main(String[] args) {
//测试: 调用猫类
Cat c = new Cat();
printAnimal(c);
System.out.println("-------------");

    //测试: 调用狗类  
    Dog d = new Dog();  
    printAnimal(d);  
}

//需求: 定义方法, 接收动物类型的对象, 然后调用其eat()方法  
//方式二: 采用多态解决.  
public static void printAnimal(Animal an) {     //Animal an = ?  
    an.eat();  
}

//方式一: Low版本, 一种动物, 一个方法.

//针对于Cat(猫)类  
public static void printAnimal(Cat c) {  
    c.eat();  
}

//针对于Dog(狗)类  
public static void printAnimal(Dog d) {  
    d.eat();  
}  

}

package com.it.demo11_animal;

/*
案例: 演示instanceof关键字的用法

instanceof关键字详解:  
    格式:  
        对象名 instanceof 数据类型(类名)  
    作用:  
        判断前边的对象, 是否是后边的数据类型, true: 是, false: 不是

*/
public class AnimalTest04 {
public static void main(String[] args) {
//测试: 调用猫类
Cat c = new Cat();
printAnimal(c);
System.out.println("-------------");

    //测试: 调用狗类  
    Dog d = new Dog();  
    printAnimal(d);  
}

//需求: 定义方法, 接收动物类型的对象, 然后调用其eat()方法  
//方式二: 采用多态解决.  
public static void printAnimal(Animal an) {     //Animal an = ?  
    //通用功能  
    an.eat();

    //某些子类独有的功能  
    if (an instanceof Cat) {  
        Cat c = (Cat)an;  
        c.catchMouse();  
    } else if (an instanceof Dog) {  
        Dog d = (Dog)an;  
        d.lookHome();  
    }  
}

/* //方式一: Low版本, 一种动物, 一个方法.

//针对于Cat(猫)类  
public static void printAnimal(Cat c) {  
    c.eat();  
    c.catchMouse();  
}

//针对于Dog(狗)类  
public static void printAnimal(Dog d) {  
    d.eat();  
    d.lookHome();  
}\*/  

}

package com.it.demo01_final;

//父类
//public final class Father extends Object{ //final修饰的类: 不能被继承, 但是可以继承其他类.
public class Father{
int a = 10;
public final void show() {
System.out.println("这个是绝密文件, 不能动!");
}

}

package com.it.demo01_final;

//子类
public class Son extends Father{
final int age = 20;

//重写父类的show()方法, 这样写会报错, 因为父类用final修饰的方法, 子类无法重写.  
/\*@Override  
public void show() {  
    System.out.println("这个是垃圾文件, 赶紧删除!");  
}\*/  

}

package com.it.demo01_final;

/*
案例: 演示final关键字

需求:  
    1.定义Father类, 并定义它的子类Son.  
    2.先用final修饰Father类, 看Son类是否还能继承Father类.  
    3.在Son类中定义成员变量age, 并用final修饰, 然后尝试给其重新赋值, 并观察结果.  
    4.在Father类中定义show()方法, 然后用final修饰, 看Son类是否能重写该方法.

final关键字简介:  
    概述:  
        它是一个关键字, 表示 最终 的意思, 可以修饰类, 成员变量, 成员方法.  
    特点:     //记忆  
        修饰的类:           不能被继承, 但是可以继承其他类.  
        修饰的变量:         是一个常量, 只能赋值一次.  
        修饰的成员方法:     不能被子类重写.  

*/
public class FatherTest {
public static void main(String[] args) {
//演示final修饰局部变量.
final int a = 10;
//a = 20; //报错, final修饰的变量: 是一个常量, 只能赋值一次.
System.out.println(a);
System.out.println("------------------");

    //演示final修饰成员变量.  
    Son s = new Son();  
    //s.age = 30;  报错, final修饰的变量:  是一个常量, 只能赋值一次.  
    System.out.println(s.age);  
    System.out.println("------------------");  
    s.show();

}  

}

package com.it.demo01_final;

/*
案例: 演示final修饰的变量的特点.

结论(记忆):  
    1. final修饰的变量如果是基本类型: 说明值不能变化.  
    2. final修饰的变量如果是引用类型: 说明地址值不能变化, 但是属性值可以变化.  

*/
public class FatherTest02 {
public static void main(String[] args) {
//演示: final修饰的变量如果是基本类型: 说明值不能变化.
final int a = 10;
//a = 20; //报错: final修饰的变量如果是基本类型: 说明值不能变化.

    //演示: final修饰的变量如果是引用类型: 说明地址值不能变化, 但是属性值可以变化.  
    final Father f = new Father();  
    //f = new Father();   //报错, 说明地址值不能变化  
    f.a = 100;          //不报错, 但是属性值可以变化  
    System.out.println(f.a);  
}  

}

package com.it.demo02_static;

//学生类
public class Student {
String name; //姓名
int age; //年龄
static String graduateFrom; //毕业院校, 共享

public Student() {  
}

public Student(String name, int age) {  
    this.name = name;  
    this.age = age;  
}

public Student(String name, int age, String graduateFrom) {  
    this.name = name;  
    this.age = age;  
    this.graduateFrom = graduateFrom;  
}

//定义show()方法, 用来打印上述的各个属性信息.  
public String show() {  
    return name + "..." + age + "..." + graduateFrom;  
}  

}

package com.it.demo02_static;

/*
案例: 演示static关键字的特点

需求:  
    1.定义学生类, 属性为姓名, 年龄, 毕业院校(graduateFrom).  
    2.在学生类中定义show()方法, 用来打印上述的各个属性信息.  
    3.在测试类的main方法中, 创建学生对象, 并调用学生类的各个成员.

static简介:  
    概述:  
        它是一个关键字, 表示 静态 的意思, 可以修饰成员变量, 成员方法.  
    特点:  
        1. 静态成员是随着类的加载而加载的.  
        2. 静态成员是优先于对象存在的.  
        3. 静态成员可以被该类下所有的对象所共享.  
            //这个判断是否使用静态的一个标准.  
        4. 静态成员可以被 类名. 的形式调用,  也可以通过 对象名. 的形式调用,  
           推荐使用前者.  

*/
public class StudentTest {
public static void main(String[] args) {
//前提: 这些学生都是同一个大学的学生.
//学生来自于: 传智大学
Student.graduateFrom = "传智大学";

    //创建学生, 属性值为: 刘亦菲, 33, 北影, 打印该学生的信息.  
    Student s1 = new Student("刘亦菲", 33);  
    System.out.println(s1.show());

    //创建学生, 属性值为: 赵丽颖, 31, 北影, 打印该学生的信息.  
    Student s2 = new Student("赵丽颖", 31, "北影");  
    System.out.println(s2.show());

    //创建学生, 属性值为: 高圆圆, 35, 北影, 打印该学生的信息.  
    Student s3 = new Student("高圆圆", 35);  
    System.out.println(s3.show());  
}  

}

package com.it.demo03_static;

//学生类
public class Student {
//属性
String name; //姓名, 非静态成员变量
static int age; //年龄, 静态成员变量

//行为  
public void show1() {  
    System.out.println(name);   //非静态成员变量  
    System.out.println(age);    //静态成员变量  
    show2();                     //非静态方法  
    show4();                     //静态方法

    System.out.println("非静态 show1()方法");  
}

public void show2() {  
    System.out.println("非静态 show2方法");  
}

public static void show3() {  
    //System.out.println(name);   //非静态成员变量  
    System.out.println(age);    //静态成员变量  
    //show2();                     //非静态方法  
    show4();                     //静态方法

    System.out.println("静态 show3()方法");  
}

public static void show4() {  
    System.out.println("静态 show4()方法");  
}  

}

package com.it.demo03_static;

/*
案例: 演示static的访问特点和注意事项.

需求:  
    1.定义学生类, 属性为姓名和年龄(静态修饰), 非静态方法show1(),show2(), 静态方法show3(), show4().  
    2.尝试在show1()方法中, 调用: 姓名, 年龄, show2(), show4().  
     结论: 非静态方法可以访问所有成员(非静态变量和方法, 静态变量和方法)  
    3.尝试在show3()方法中, 调用: 姓名, 年龄, show2(), show4().  
     结论: 静态方法只能访问静态成员.

结论(记忆):  
    1. 静态成员方法只能访问静态成员(静态成员变量和静态成员方法).  
        大白话理解: 静态只能访问静态.  
    2. 在静态方法中, 是没有this, super关键字的.  
    3.因为静态的内容是随着类的加载而加载, 而this和super是随着对象的创建而存在.  
        即: 先进内存的, 不能访问后进内存的.

*/
public class StudentTest {
public static void main(String[] args) {
//需求: 调用Student#show1()
Student s = new Student();
s.show1(); //非静态成员方法, 可以访问非静态成员, 也可以访问静态成员.
System.out.println("---------------------");

    //需求: 调用Student#show3();  
    Student.show3();

}  

}

package com.it.demo04_abstract;

/*
案例: 抽象类入门.

结论(记忆):  
    1. 没有方法体的方法叫; 抽象方法.  
    2. 有抽象方法的类一定是抽象类.  
    3. 抽象方法和抽象类都用关键字: abstract修饰.  

*/
public abstract class Animal {

//抽象方法  
public abstract void eat();

//非抽象方法  
/\*public void eat() {  
    System.out.println("动物会吃!");  
}\*/  

}

package com.it.demo04_abstract;

//测试类
public class AnimalTest {
public static void main(String[] args) {
//需求: 调用Animal#eat()方法
//下边这个代码是无意义的, 并没有给出具体的动物.

    //报错原因: 抽象类不能直接实例化.  
    //Animal an = new Animal();       //动物是动物  
    //an.eat();                       //动物会吃!  
}  

}

package com.it.demo05_animal;

//父类, 动物类.
public abstract class Animal {
//抽象方法, 吃饭
public abstract void eat();

//非抽象方法, 睡觉.
public void sleep() {
System.out.println("动物要睡觉!");
}
}

package com.it.demo05_animal;

//非抽象的子类, 猫类
public class Cat extends Animal{
//如果是普通类: 则必须重写父抽象类中 所有的抽象方法.

@Override  
public void eat() {  
    System.out.println("猫吃鱼");  
}  

}

package com.it.demo05_animal;

//抽象的子类, 狗类

//抽象类的子类: 如果是抽象类, 则可以不用重写父抽象类中的 抽象方法.
public abstract class Dog extends Animal{
}

package com.it.demo05_animal;

/*
案例: 演示抽象类的特点

需求:  
    1.定义抽象类Animal , 类中有一个抽象方法eat(), 还有一个非抽象方法sleep().  
    2.尝试在测试类中, 创建Animal类的对象, 并观察结果.  
    3.创建普通类Cat, 继承Animal类, 观察是否需要重写Animal#eat()方法.  
    4.创建抽象类Dog, 继承Animal类, 观察是否需要重写Animal#eat()方法.

 结论(记忆:):  
    1. 抽象方法和抽象类都要用 abstract 关键字修饰.  
    2. 有抽象方法的类一定是抽象类, 但是抽象类中不一定有抽象方法.  
    3. 抽象类不能直接实例化.  
        那抽象类如何实例化呢?  
            可以通过 多态的形式创建其子类对象, 来完成抽象类的初始化, 这种做法叫: 抽象类多态.  
    4. 抽象类的子类:  
        如果是普通类: 则必须重写父抽象类中 所有的抽象方法.  
        如果是抽象类: 则可以不用重写父抽象类中的 抽象方法.  

*/
public class AnimalTest {
public static void main(String[] args) {
//Animal an = new Animal(); //报错, 抽象类不能直接实例化

    //那抽象类如何实例化呢?  
    //抽象类多态  
    Animal an = new Cat();  
    an.eat();

}  

}

package com.it.demo06_abstract;

//人类, 抽象类
public abstract class Person {
//变量
int age;
//常量, 系统不给默认值, 留给用户来设置.
final String country = "中国"; //null

//构造方法  
public Person() {  
}  
public Person(int age) {  
    this.age = age;  
}

//非抽象方法  
public void eat() {  
    System.out.println("人要吃饭!");  
}

//抽象方法  
public abstract void sleep();  

}

package com.it.demo06_abstract;

/*
需求: 演示抽象类的成员特点, 即抽象类中可以写什么.

需求:  
    1.定义抽象类Person, 在类中定义变量age, 常量country, 空参, 全参构造.  
    2.在Person类中定义非抽象方法show(), 抽象方法eat().  
    3.在测试类的main方法中, 创建Person类的对象, 并调用类中的成员.

 结论(记忆):  
    专业版:  
        抽象类中可以写变量, 常量, 构造方法, 非抽象方法, 抽象方法.  
    大白话版:  
        抽象类比普通类多一种抽象方法, 而且抽象方法还可以不写.  

*/
public class PersonTest {
public static void main(String[] args) {

}  

}

package com.it.demo08_interface;

/*
案例: 演示接口的成员特点, 即: 接口中可以写什么.

结论:  
    1. JDK1.8以前, 接口中有且只能有 常量 和 抽象方法, 原因是因为:  
        接口中的成员变量有默认修饰符: public static final  
        接口中的成员方法有默认就是福: public abstract  
    2. JDK1.8开始, 接口中可以写如下成员:  
        静态方法: 直接写即可, 和以前的规则一样.  
        默认方法: 即非静态方法, 要用 default 关键字修饰.  

*/
public interface Inner {
//接口中的成员变量有默认修饰符: public static final
public static final int age = 20;

//接口中的成员方法有默认就是福: public abstract  
//public abstract void eat();  
//上述代码可以简写成: 如下的形式  
void eat();

public static void show() {  
    System.out.println("JDK1.8开始, 接口中可以写 静态方法了");  
}

public default void method() {  
    System.out.println("JDK1.8开始, 接口中可以写 非静态(默认)方法了");  
}  

}

package com.it.demo08_interface;

//测试类
public class InnerTest {
public static void main(String[] args) {
//调用接口中的 成员变量, 其实是一个常量
//Inner.age = 30; //报错, 常量值只能赋值一次, 不能修改.
System.out.println(Inner.age);

    //调用接口中的 成员方法  
    Inner.show();

    //下述代码会报错, 因为method()是默认方法(非静态), 必须通过 对象名. 的形式调用.  
    //Inner.method();  
}  

}

package com.it.demo08_interface;

//自定义接口Jumpping, 表示具有跳高功能.
public interface Jumpping {

//jump()方法, 表示具有跳高功能  
public abstract void jump();  

}

package com.it.demo08_interface;

/*
案例: 演示接口的特点.

需求:  
    1.定义Jumpping接口, 接口中有一个抽象方法jump().  
    2.定义Cat类, 实现Jumpping接口, 重写jump()方法.  
    3.在测试类的main方法中, 创建Jumpping接口对象, 并调用其jump()方法

结论(记忆):  
    1. 接口用 interface 关键字修饰.  
    2.  

类和接口之间是实现关系, 用关键字 implements 来修饰.
3. 接口不能直接实例化.
那接口如何实例化呢?
可以通过多态的形式, 创建其子类对象, 来完成接口的实例化. 这种写法叫: 接口多态.
4. 接口的子类:
如果是普通类: 则必须重写父接口中 所有的抽象方法.
如果是抽象类: 则可以不用重写父接口中的 抽象方法.

*/
public class JumpTest {
public static void main(String[] args) {
//演示: 接口不能直接实例化
//Jumpping jm = new Jumpping(); //接口不能直接实例化

    // 那接口如何实例化呢?  
    Jumpping jm = new Cat();          //接口多态  
}  

}

package com.it.demo08_interface;

//自定义的猫类, 实现Jumpping接口

//接口的子类: 如果是抽象类, 则可以不用重写父接口中的 抽象方法.
//public abstract class Cat implements Jumpping{

//接口的子类: 如果是普通类, 则必须重写父接口中 所有的抽象方法.
public class Cat implements Jumpping{
@Override
public void jump() {
System.out.println("猫会跳高!");
}
}

package com.it.demo09_interface_class;

public class A {
}

package com.it.demo09_interface_class;

public class B {
}

package com.it.demo09_interface_class;

//演示: 类与类之间: 继承关系, 只能单继承, 不能多继承, 但是可以多层继承.
//public class C extends B, A{ //报错

//演示: 类和接口之间: 实现关系, 可以单实现, 也可以多实现, 还可以在继承一个类的同时实现多个接口.
//public class C implements Inner1{ //单实现

//public class C implements Inner1,Inner2{ //多实现

//public class C extends B implements Inner1,Inner2{ //继承一个类的同时实现多个接口.

public class C implements Inner3{
@Override
public void show3() {

}

@Override  
public void show1() {

}

@Override  
public void show2() {

}  

}

package com.it.demo09_interface_class;

public interface Inner1 {
void show1();
}

package com.it.demo09_interface_class;

public interface Inner2 {
void show1();
void show2();
}

package com.it.demo09_interface_class;

//演示: 接口与接口之间的关系: 继承关系, 可以单继承, 也可以多继承.
public interface Inner3 extends Inner2, Inner1{
void show3();
}

package com.it.demo09_interface_class;

/*
案例: 演示接口 和 类之间的关系.
类与类之间:
继承关系, 只能单继承, 不能多继承, 但是可以多层继承.
类与接口直接:
实现关系, 可以单实现, 也可以多实现, 还可以在继承一个类的同时实现多个接口.
接口与接口之间:
继承关系, 可以单继承, 也可以多继承.
*/
public class Test {

}

package com.itheima.demo11_package;

import java.util.Scanner;
import java.util.HashSet;
import java.io.InputStreamReader;

/*
案例: 包的详解

包(package)的简介:  
    概述:  
        包就是文件夹, 用来区分重名类的, 多级包之间用.隔开, 一般是命名格式为: 公司域名反写 + 项目名 + 部门名(编号) + 功能模块 格式.  
    常见的分包方式:  
        基本划分: 一般是按照功能或者模块划分的  
            按照模块划分:  
                com.itheima.student     学生模块  
                    AddStudent  
                    DeleteStudent  
                    UpdateStudent  
                    SelectStudent  
                com.itheima.teacher     老师模块  
                    AddTeacher  
                    DeleteTeacher  
                    UpdateTeacher  
                    SelectTeacher  
             按照功能划分:  
                com.itheima.add  
                    AddStudent  
                    AddTeacher  
                    ...  
                com.itheima.delete  
                    DeleteTeacher  
                    DeleteStudent  
                    ...  
        高级划分: 按照具体的业务划分的  
            com.it.controller      控制层  
            com.it.service         业务层  
            com.it.dao             数据访问层  
            com.it.utils           存放的是所有的工具类  
            com.it.pojo            存放所有的JavaBean类  
            ...

    格式:  
        package 包名1.包名2.包名3;  
    注意事项:  
        1.package语句必须是程序的第一条可执行的代码.  
        2.package语句在一个.java文件中只能有一个.  

*/
public class Demo01 {
public static void main(String[] args) {

}  

}

//class A{ }

package com.it.demo10_exercise;

//接口, 表示具有说英语的功能
public interface SpeakEnglish {
void speakEnglish();
}

package com.it.demo10_exercise;

//父类, 人类
public abstract class Person {
//属性: 姓名, 年龄
private String name;
private int age;

public Person() {  
}

public Person(String name, int age) {  
    this.name = name;  
    this.age = age;  
}

public String getName() {  
    return name;  
}

public void setName(String name) {  
    this.name = name;  
}

public int getAge() {  
    return age;  
}

public void setAge(int age) {  
    this.age = age;  
}

//行为: 吃  
public abstract void eat();  

}

package com.it.demo10_exercise;

//篮球教练类, 需要继承: 教练类
public class BasketballCoach extends Coach{
//构造方法, 子类空参访问父类空参, 子类全参访问父类全参.
public BasketballCoach() {
}

public BasketballCoach(String name, int age) {  
    super(name, age);  
}

//重写吃的方法  
@Override  
public void eat() {  
    System.out.println("篮球教练吃羊肉, 喝牛奶");  
}

//重写教的方法  
@Override  
public void teach() {  
    System.out.println("篮球教练教如何运球和投篮");  
}  

}

package com.it.demo10_exercise;

//教练类, 需要继承人类
public abstract class Coach extends Person{
//构造方法, 子类空参访问父类空参, 子类全参访问父类全参.
public Coach() {
}

public Coach(String name, int age) {  
    super(name, age);  
}

//行为: 教学  
public abstract void teach();

}

package com.it.demo10_exercise;

//运动员类, 需要继承人类
public abstract class Player extends Person{
//构造方法, 子类空参访问父类空参, 子类全参访问父类全参.
public Player() {
}

public Player(String name, int age) {  
    super(name, age);  
}

//行为: 学习  
public abstract void study();

}

package com.it.demo10_exercise;

//篮球运动员类, 需要继承: 运动员类
public class BasketballPlayer extends Player{
//构造方法, 子类空参访问父类空参, 子类全参访问父类全参.
public BasketballPlayer() {
}

public BasketballPlayer(String name, int age) {  
    super(name, age);  
}

//重写学习的功能  
@Override  
public void study() {  
    System.out.println("篮球运动员学习如何运球和投篮");  
}

//重写吃饭的功能  
@Override  
public void eat() {  
    System.out.println("篮球运动员吃牛肉, 喝羊奶");  
}  

}

package com.it.demo10_exercise;

//乒乓球运动员, 需要继承 运动员类, 还得实现 说英语的接口.
public class PingPangPlayer extends Player implements SpeakEnglish{
//构造方法, 子类空参访问父类空参, 子类全参访问父类全参.
public PingPangPlayer() {
}

public PingPangPlayer(String name, int age) {  
    super(name, age);  
}

//重写吃的功能  
@Override  
public void eat() {  
    System.out.println("乒乓球运动员吃大白菜, 喝小米粥");  
}

//重写学习的功能  
@Override  
public void study() {  
    System.out.println("乒乓球运动员学习如何发球");  
}

//重写说英语的功能  
@Override  
public void speakEnglish() {  
    System.out.println("乒乓球运动员需要学习如何 说英语");  
}  

}

package com.it.demo10_exercise;

//篮球教练类, 需要继承: 教练类
public class BasketballCoach extends Coach{
//构造方法, 子类空参访问父类空参, 子类全参访问父类全参.
public BasketballCoach() {
}

public BasketballCoach(String name, int age) {  
    super(name, age);  
}

//重写吃的方法  
@Override  
public void eat() {  
    System.out.println("篮球教练吃羊肉, 喝牛奶");  
}

//重写教的方法  
@Override  
public void teach() {  
    System.out.println("篮球教练教如何运球和投篮");  
}  

}

package com.it.demo10_exercise;

//乒乓球教练, 需要继承 教练类, 还得实现 说英语的接口.
public class PingPangCoach extends Coach implements SpeakEnglish{
//构造方法, 子类空参访问父类空参, 子类全参访问父类全参.
public PingPangCoach() {
}

public PingPangCoach(String name, int age) {  
    super(name, age);  
}

//重写吃的方法  
@Override  
public void eat() {  
    System.out.println("乒乓球运动员吃小白菜, 喝大米粥");  
}

//重写教的方法  
@Override  
public void teach() {  
    System.out.println("乒乓球教练教如何发球");  
}

//重写说英语的方法  
@Override  
public void speakEnglish() {  
    System.out.println("乒乓球教练需要学习如何 说英语");  
}  

}

package com.it;

/*
案例: 演示各个权限修饰符的用法.

结论(记忆):  
    1. 测试图解  
                                         private     默认      protected       public  
        本类中:                            √        √          √              √  
        同包下的类(子类或者无关类均可):              √          √              √  
        不同包下的子类:                                          √              √  
        不同包下的无关类:                                                        √

    2. 四大访问权限修饰符的权限从小到大分别是:  
        private < 默认 < protected < public  
    3. 大白话总结的结论(必须记忆):  
        private:    强调的是给 本类       使用的.  
        默认:       强调的是给 同包下的类 使用的.  
        protected:  强调的是给 子类       使用的.  
        public:     强调的是给 大家       使用的.

        以后写代码的时候, 如非必要, 基本都是: 成员变量全部用private修饰, 其他都用public修饰.  

*/
public class Father {
private void show1() {
System.out.println("private show1()");
}

void show2() {  
    System.out.println("默认 show1()");  
}

protected void show3() {  
    System.out.println("protected show1()");  
}

public void show4() {  
    System.out.println("public show1()");  
}

public static void main(String\[\] args) {  
    //创建Father类的对象, 调用四个方法  
    Father f = new Father();  
    f.show1();  
    f.show2();  
    f.show3();  
    f.show4();  
}  

}

package com.it;

//测试四大访问权限修饰符, 该类和Father类的关系: 同包下的子类.
public class Son extends Father {
public static void main(String[] args) {
//创建Father类的对象, 调用四个方法
Father f = new Father();
//f.show1(); private
f.show2();
f.show3();
f.show4();
}
}

package cn.it;

//老师类
public class Teacher {
public void method() {
System.out.println("Teacher类的 method()方法");
}

}

package com.it;

//学生类
public class Student {
public void show() {
System.out.println("Student类的 show()方法");
}
}

package com.it;

/*
案例: 演示导包.

导包简介:  
    概述:  
        当我们使用不同包下的类的时候, 就需要导包. 如果是同包下的类, 可以直接使用.  
    格式:  
        import 包名1.包名2.类名;      //只导入一个具体的包, 推荐使用.  
        import 包名1.包名2.\*;         //导入包2下所有的内容(包括所有的类和接口)  

*/
public class Test {
//main方法作为程序的主入口
public static void main(String[] args) {
//需求1: 调用Student#show(), 同包下的类, 直接用, 无需导包.
Student s = new Student();
s.show();

    //需求2: 调用Teacher#method()方法, 不同包下的类的使用.  
    //方式一: 写全类名(即: 包名 + 类名)  
    cn.it.Teacher t1 = new cn.itcast.Teacher();  
    t1.method();  
    System.out.println("-------------------");

    //方式二: 导包  
    Teacher t2 = new Teacher();  
    t2.method();  
}  

}

package com.it;

//测试四大访问权限修饰符, 该类和Father类的关系: 同包下的无关类.
public class Test02 {
public static void main(String[] args) {
//创建Father类的对象, 调用四个方法
Father f = new Father();
//f.show1(); private
f.show2();
f.show3();
f.show4();
}
}