一、包
1、基本介绍
- 包的本质就是创建不同的文件夹来保存类文件
- 定义包
package 【包名】;
- 引入包
import 【包名】;
2、包的作用
-
区分相同名字的类
-
可以很好的管理类
-
控制访问权限
3、包的命名
(1)基本介绍
-
命名规则:只能包含数字、字母、下划线、小圆点,不能用数字开头,不能是关键字或保留字
-
命名规范:一般是小写字母 + 小圆点
(2)演示
- 公司开发
com.【公司名】.【项目名】.【业务模块名】;
- 团队开发
team.【团队名】.【项目名】.【业务模块名】;
4、常用包
包 | 说明 |
---|---|
java.lang.* | 基本包,默认引用 |
java.util.* | 系统提供的工具包,有大量工具类 |
java.net.* | 网络包 |
java.awt.* | GUI |
5、注意事项
-
package:作用是声明当前类所在包,需要放在最上方,一个类中最多只有一条 package 语句
-
import:需要放置在 package语句下方
二、访问修饰符
1、基本介绍
-
公开级别:public,对外公开
-
受保护级别:protected,对子类和同一个包中的类公开
-
默认级别:无修饰符,向同一个包的类公开
-
私有级别:private,只有类本身可以访问
访问级别 | 访问修饰符 | 同类 | 同包不同类(不含子类) | 同包子类 | 不同包不同类(不含子类) | 不同包子类 |
---|---|---|---|---|---|---|
公开 | public | √ | √ | √ | √ | √ |
受保护 | protected | √ | √ | √ | - | √(注意) |
默认 | 无修饰符 | √ | √ | √ | - | - |
私有 | private | √ | - | - | - | - |
2、注意事项
-
访问修饰符可以用来修饰类中的属性,成员方法
-
只有 public 和无修饰符才能修饰类
3、演示
- 同类
package com.my.modifier;public class A {public int n1 = 100;protected int n2 = 200;int n3 = 300;private int n4 = 400;public void m() {System.out.println(n1);System.out.println(n2);System.out.println(n3);System.out.println(n4);}
}
- 同包不同类(不含子类)
package com.my.modifier;public class B {public void m() {A a = new A();System.out.println(a.n1);System.out.println(a.n2);System.out.println(a.n3);
// System.out.println(a.n4); // 'n4' has private access in 'com.my.modifier.A'}
}
- 不同包不同类
package com.my.modifier.test;import com.my.modifier.A;public class C {public void m() {A a = new A();System.out.println(a.n1);
// System.out.println(a.n2); // 'n2' has protected access in 'com.my.modifier.A'
// System.out.println(a.n3); // 'n3' is not public in 'com.my.modifier.A'. Cannot be accessed from outside package
// System.out.println(a.n4); // 'n4' has private access in 'com.my.modifier.A'}
}
- 同包子类
package com.my.modifier;public class Ac1 extends A {public void m() {System.out.println(n1);System.out.println(n2);System.out.println(n3);
// System.out.println(n4); // 'n4' has private access in 'com.my.modifier.A'}
}
- 不同包子类
package com.my.modifier.test;import com.my.modifier.A;public class Ac2 extends A {public void m() {System.out.println(n1);System.out.println(n2);
// System.out.println(a.n3); // 'n3' is not public in 'com.my.modifier.A'. Cannot be accessed from outside package
// System.out.println(a.n4); // 'n4' has private access in 'com.my.modifier.A'}
}
三、封装
1、基本介绍
- 把数据和对数据的操作进行封装,数据被保护在内部,只有通过被授权的操作才能对数据进行操作
2、封装的好处
-
隐藏实现细节
-
对数据进行验证,保证安全合理
3、封装的实现步骤
-
将属性私有化
-
提供一个公共的 set 方法,用于对属性判断并赋值
-
提供一个公共的 get 方法,用于获取属性的值
4、具体实现
- Person.java
package com.my.intermediate;public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}// 获取 name 的 get 方法public String getName() {return name;}// 设置 name 的 set 方法public void setName(String name) {this.name = name;}// 获取 age 的 get 方法public int getAge() {return age;}// 设置 age 的 set 方法public void setAge(int age) {this.age = age;}
}
四、继承
1、基本介绍
- 当多个类存在相同的属性和方法时,可以从中抽取出父类,在父类中定义相同的属性和方法,子类则只需继承父类
class 子类 extends 父类 {}
-
父类又名超类,基类
-
子类又名派生类,子类会拥有父类定义的属性和方法
2、注意事项
-
子类继承了父类所有的属性和方法,但是子类不能直接访问父类的私有属性,需要通过公共的方法
-
子类创建对象时会调用父类的无参构造器,完成父类初始化
-
子类创建对象时,如果父类没有提供无参构造器,则必须在子类的构造器中使用 super 指定使用父类的某个构造器完成父类初始化
-
显式调用父类的构造器
super(【参数列表】);
-
super 需要放置在构造器的第一行
-
super 和 this都只能放在构造器第一行,二者不能共存
-
Java 中的所有类都是 Object 的子类
-
父类构造器的调用不限于直接父类,将一直往上追溯到 Object 类(顶级父类)
-
子类最多只能继承一个父类
3、具体实现
- ExtendsTest.java
package com.my.intermediate;public class ExtendsTest {public static void main(String[] args) {Student student = new Student("小明", 12);Teacher teacher = new Teacher("张老师", 30);student.say();teacher.say();}
}// 父类
class People {private String name;private int age;public People(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;}
}// 子类
class Student extends People {public Student(String name, int age) {super(name, age);}public void say() {System.out.println("我是学生" + getName());}
}// 子类
class Teacher extends People {public Teacher(String name, int age) {super(name, age);}public void say() {System.out.println("我是老师" + getName());}
}
五、super
1、基本介绍
- super 代表父类的引用,用于访问父类的属性,方法,构造器
- 访问父类属性,但不能访问父类的私有属性
super.【属性名】;
- 访问父类方法,但不能访问父类的私有方法
super.【方法名】;
- 访问父类构造器
super(【参数列表】);
2、super 的好处
- 调用父类构造器,分工明确,父类属性由父类初始化,子类属性由子类初始化
3、注意事项
-
子类和父类中的成员(属性或方法)重名时,访问父类成员,必须使用 super,如果没有重名,使用 super 和 this 访问效果一致
-
super 的访问不限于直接父类,如果多个基类中都有同名的成员,super 的访问遵循就近原则
六、方法重写
1、基本介绍
- 方法重写就是子类有一个方法,和父类的某个方法的名称,返回类型,参数一致
2、注意事项
-
子类重写方法的形参列表,方法名称,要和父类方法的形参列表,方法名称一致
-
子类重写方法的返回类型和父类的返回类型一致,或者是父类返回类型的子类
-
子类重写方法不能缩小父类方法的访问权限
3、具体实现
- OverwriteTest.java
package com.my.intermediate;public class OverwriteTest {public static void main(String[] args) {Dog dog = new Dog();dog.shout();}
}class Animal {// 父类的 shout 方法public void shout() {System.out.println("动物哇哇叫!!!");}
}class Dog extends Animal{// 进行方法重写,父类的 shout 方法@Overridepublic void shout() {System.out.println("小狗汪汪叫!!!");}
}
七、多态
1、基本介绍
- 方法或对象具有多种形态,建立在封装和继承的基础之上
2、多态的具体体现
(1)方法的多态
- 方法的重载和重写体现多态
(2)对象的多态
- 一个对象的编译类型和运行类型可以不一致
Animal animal = new Dog(); // 编译类型是 Animal,运行类型是 Dog
animal = new Cat(); // animal 的运行类型变为 Cat,编译类型仍是 Animal
-
对象的编译类型在定义对象时就确定了,不能改变
-
对象的运行类型是可以改变的
3、注意事项
-
多态的前提是两个对象(类)存在继承关系
-
属性没有重写
4、具体实现
- PolyObjectTest.java
package com.my.intermediate;public class PolyObjectTest {public static void main(String[] args) {Person person1 = new Student();Person person2 = new Driver();person1.say();person2.say();}
}class Person {public void say() {System.out.println("自我介绍");}
}class Student extends Person {@Overridepublic void say() {System.out.println("我是学生");}
}class Driver extends Person {@Overridepublic void say() {System.out.println("我是司机");}
}
5、补充
(1)向上转型
- 本质是父类的引用指向子类的对象
【父类类型】 【引用名】 = new 【子类类型】();
- 可以调用父类的所有成员,但需遵守访问权限,不能调用子类的特有成员
(2)向下转型
【子类类型】 【引用名】 = (【子类类型】) 【父类引用】;
-
只能强转父类的引用,不能强转父类的对象
-
要求父类的引用必须指向当前目标类型的对象
-
可以调用子类中的所有成员
(3)instanceOf 比较操作符
- 判断对象的运行类型是否为某类型或某类型的子类型
6、多态的应用
(1)基本介绍
-
多态参数:方法定义的形参类型为父类类型,实参类型允许为子类型
-
多态数组
(2)具体实现
- PolyObjectExercise.java
package com.my.intermediate;public class PolyObjectExercise {public static void main(String[] args) {Master master = new Master("杰克");Dog dog = new Dog("阿黄");Cat cat = new Cat("咪咪");Meat meat = new Meat("肉");Fish fish = new Fish("鱼");master.feed(dog, meat);master.feed(cat, fish);// 测试向上转型System.out.println("====================");Animal animal1 = new Dog("大黄");animal1.sleep(animal1);// 测试向下转型System.out.println("====================");Animal animal2 = new Cat("大橘");Cat myCat = (Cat) animal2;myCat.shout(myCat.getName());// 测试比较操作符System.out.println("====================");System.out.println(dog instanceof Dog);System.out.println(dog instanceof Animal);}
}class Master {private String name;public Master(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void feed(Animal animal, Food food) {System.out.println("主人" + this.getName() + "给" + animal.getName() + "喂食" + food.getName());}
}class Animal {private String name;public Animal(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void sleep(Animal animal) {System.out.println(animal.name + "在睡觉");}
}class Food {private String name;public Food(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}class Dog extends Animal {public Dog(String name) {super(name);}
}class Cat extends Animal {public Cat(String name) {super(name);}public void shout(String name) {System.out.println(name + "喵喵叫");}
}class Meat extends Food {public Meat(String name) {super(name);}
}class Fish extends Food {public Fish(String name) {super(name);}
}
- PolyArrTest.java
package com.my.intermediate;public class PolyArrTest {public static void main(String[] args) {Person[] persons = new Person[5];persons[0] = new Person("杰克", 20);persons[1] = new Teacher("张老师", 30, 3000);persons[2] = new Teacher("王老师", 40, 4000);persons[3] = new Student("小明", 12, 89);persons[4] = new Student("小李", 14, 78);// 遍历多态数组for (int i = 0; i < persons.length; i++) {if (persons[i] instanceof Student) {((Student) persons[i]).study();} else if (persons[i] instanceof Teacher) {((Teacher) persons[i]).teach();} else {System.out.println(persons[i].say());}}}
}class Person {private String name;private int age;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 String say() {return "name: " + name + ", age: " + age;}
}class Student extends Person {private double score;public Student(String name, int age, double score) {super(name, age);this.score = score;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}@Overridepublic String say() {return super.say() + " score:" + score;}// 特有方法public void study() {System.out.println(this.getName() + "在学习");}
}class Teacher extends Person {private double money;public Teacher(String name, int age, double money) {super(name, age);this.money = money;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}@Overridepublic String say() {return super.say() + " money" + money;}// 特有方法public void teach() {System.out.println(this.getName() + "在教学");}
}
八、动态绑定机制
1、基本介绍
-
当调用对象方法时,该方法会和该对象的内存地址 / 运行类型绑定
-
当调用对象属性时,没有动态绑定机制,哪里声明哪里调用
2、演示
- DynamicBindingTest.java
package com.my.intermediate;public class DynamicBindingTest {public static void main(String[] args) {A a = new B();System.out.println(a.sum());System.out.println(a.newSum());}
}class A {int i = 10;public int sum() {return getI() + 10;}public int newSum() {return i + 10;}public int getI() {return i;}
}class B extends A {int i = 20;// public int sum() {
// return i + 20;
// }public int newSum() {return i + 10;}public int getI() {return i;}
}
- 输出结果
30
30
九、相关方法
1、== 与 equals 方法
(1)基本介绍
-
== 即可以判断基本数据类型,又可以判断引用数据类型
-
== 如果判断基本数据类型,判断的是值是否相等
-
== 如果判断引用数据类型,判断的是地址是否相等
-
equals 方法是 Object 类中的方法,只能判断引用数据类型
-
equals 方法默认判断地址是否相等,子类往往会重写该方法,用于判断内容是否相等(例如 String)
(2)演示
- EqualsExercise.java
package com.my.intermediate;public class EqualsExercise {public static void main(String[] args) {Person jack = new Person("jack", 10, '男');Person tom = new Person("tom", 10, '男');System.out.println(jack.equals(tom));}
}class Person {private String name;private int age;private char gender;public Person(String name, int age, char gender) {this.name = name;this.age = age;this.gender = gender;}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 char getGender() {return gender;}public void setGender(char gender) {this.gender = gender;}// 重写 Object 的 equals 方法public boolean equals(Object obj) {// 如果比较的两个对象是同一个对象,那么直接返回 trueif (this == obj) {return true;}// 类型判断if (obj instanceof Person) {// 进行向下转型Person person = (Person) obj;return this.name.equals(person.name) && this.age == person.age && this.gender == person.gender;}// 不是 Person 类型,直接返回 falsereturn false;}
}
2、hashCode 方法
(1)基本介绍
-
hashCode 方法用于返回该对象的哈希码值
-
hashCode 方法主要是为了提高具有哈希结构的容器的效率
-
两个引用,如果指向的是同一个对象,则哈希值肯定一致
-
两个引用,如果指向的是不同对象,则哈希值不一致
-
哈希值主要是根据地址来计算的,但不能完全将哈希值等价于地址
(2)基本使用
- HashCodeTest.java
package com.my.intermediate;public class HashCodeTest {public static void main(String[] args) {Person person1 = new Person();Person person2 = new Person();Person person3 = person1;System.out.println(person1.hashCode());System.out.println(person2.hashCode());System.out.println(person3.hashCode());}
}class Person {}
3、toString 方法
(1)基本介绍
-
toString 方法默认返回:全类名(包名 + 类名) + @ + 哈希值的十六进制
-
toString 方法的重写:返回对象的属性信息
-
当直接输出一个对象时,toString 方法会被默认调用
(2)基本使用
- ToStringTest.java
package com.my.intermediate;public class ToStringTest {public static void main(String[] args) {Person person = new Person("jack", 20);System.out.println(person.toString());System.out.println(person);}
}class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
4、finelize 方法
(1)基本介绍
-
当对象被回收时,系统自动调用该对象的 finelize 方法,子类可以重写该方法,做一些释放资源的操作
-
何时被回收:当某个对象没有任何引用时,JVM 会认为该对象是垃圾对象并使用垃圾回收机制销毁该对象,在销毁该对象前,会先调用 finelize 方法
-
垃圾回收机制:由系统决定调用,也可以通过调用 System.gc() 主动触发
(2)基本使用
- FinelizeTest.java
package com.my.intermediate;public class FinelizeTest {public static void main(String[] args) {Car car = new Car("宝马");car = null;System.gc();System.out.println("程序结束了");}
}class Car {private String name;public Car(String name) {this.name = name;}@Overrideprotected void finalize() throws Throwable {System.out.println("销毁了" + name);}
}