封装
-
该露的露, 该藏的藏
- 我们程序设计要追求"高内聚, 低耦合"。高内聚就是类的内部数据操作细节自己完成, 不允许外部干涉;低耦合: 仅暴露少量的方法给外部使用。
-
封装(数据的隐藏)
- 通常, 应静止直接访问一个对象中数据的实际表示, 而应通过操作来访问, 这称为信息隐藏。
-
住: 属性私有, get/set
// 类 private: 私有
public class 类名{
private String name;// 名字
private int id;// 学号
private char sex;// 性别
private int age;// 年龄
// 提供一些可以操作这个属性的方法!
// 提供一些public的get, set方法
// get 获得这个数据
public String getName(){
return this.name;
}
// set 给这个数据设置值
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(){
if (age > 120 || age < 0) {// 不合法
age = 3;
} else {
this.age = age;
}
}
// alt+insert可以自动生成getter/setter方法
}
public class Application{
public static void main(String[] args){
Student student = new Student();
student.setName("测试名称");
System.out.println(student.getName());
student.setAge(-1); // 测试
}
}
封装总结
- 提高程序的安全性, 保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护增加了
继承
- 继承的本质是对某一批类的抽象, 从而实现对现实世界更好的建模。
- extends的意思是"扩展"。子类是父类的扩展。
- Java中类只有单继承, 没有多继承!
- 继承是类和类之间的一种关系。除此以外, 类和类之间的关系还有依赖, 组合, 聚合等。
- 继承关系的俩个类, 一个为子类(派生类), 一个为父类(基类)。子类继承父类, 使用关键字extends来表示。
- 子类和父类之间, 从意义上讲应该具有"is a"的关系。
- object类
- super
- 方法重写
注: 在Java中, 所有的类, 都默认直接或者间接的继承Object
super关键字
pubilc class Application{
public static void main(String[] args){
Student student = new Student();
student.a("测试名称");
student.b();
}
}
class Student extends Person {
private String name="张三";
// 一般建议父类有无参构造, 也可使用super(参数)调用父类的有参构造
public Student(){
// 隐藏代码: 调用了父类的无参构造
super(); // 调用父类的构造器, 必须要在子类构造器的第一行
System.out.println("Student 无参执行了");
}
public void print(){
System.out.println("Student");
}
public void a(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
public void b(){
print();// Student
this.print();// Student
super.print();// Person
}
}
class Person /*extends Object*/ {
protected String name="李四";
public Person(){
System.out.println("Person无参执行了");
}
// 注: 私有的东西无法被继承!
public void print(){
System.out.println("Person");
}
}
super注意点
super注意点:
1. super调用父类的构造方法, 必须在构造方法的第一个
2. super必须只能出现在子类的方法或者构造方法中!
3. super和this不能同时调用的构造方法!
Vs this:
代表的对象不同:
this: 本身调用者这个对象
super: 代表父类对象的应用
前提
this: 没有继承也可以使用
super: 只能在继承条件下才可以使用
构造方法
this(): 本类的构造
super(): 父类的构造!
重写: 需要有继承关系, 子类重写父类的方法!
1. 方法名必须相同
2. 参数列表必须相同
3. 修饰符: 范围可以扩大: public>Protected>Default>private
4. 抛出的异常: 范围, 可以被缩小, 但不能扩大; ClassNotFoundException --> Exception(大)
重写, 子类的方法和父类必须一致, 方法体不同!
为什么需要重写:
1. 父类的功能, 子类不一定需要, 或者不一定满足!
Alt + Insert: Override;
***注: 如果一个A类被B类继承, A类的有参方法中又调用A类的无参方法, 那么无法显示写出super(), 但是隐式会在调用本类的无参方法之前调用父类的无参方法;***
方法重写
public class Application{
// 静态的方法和非静态的方法区别很大!
// 静态方法: // 方法的调用只和左边, 定义的数据类型有关
// 非静态的方法: 重写
public static void main(String[] args){
A a = new A();
a.test(); // A
a.test2();// A
// 父类的引用指向了子类
B b = new A();
b.test(); // B
b.test2(); // B
}
}
class A extends B {
public static void test(){
System.out.println("A=>test()");
}
// Override 重写
// 注解: 有功能的注释!
@Override
public void test2(){
System.out.println("A=>test()");
}
}
class B {
public static void test(){
System.out.println("B=>test()");
}
public void test2(){
System.out.println("B=>test()");
}
}
多态
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
-
一个对象的实际类型是确定的, 但可以指向对象的引用类型有很多
-
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 子类引用指向子类对象
-
注意: 多态是方法的多态, 属性没有多态性。
-
instanceof
public class Application{
public static void main(String[] args){
// 一个对象的实际类型是确定的
// new Student();
// new Person();
// 可以指向的引用类型就不确定了, 父类的引用指向子类
// Student能调动的方法都是自己的或者继承父类的!
Student student1 = new Student();
// Person父类型, 可以至相关子类, 但不能调用子类独有的方法
Person student2 = new Student();
Object student3 = new Student();
student2.run(); // 子类重写了父类的方法, 执行子类的方法
student1.run();
((Student) student2).eat();
}
}
class Person {
public void run(){
System.out.println("run");
}
}
class Student extends Person{
@Override
public void run(){
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
多态注意事项
多态注意事项:
1. 多态是方法的多态, 属性没有多态
2. 子类和父类, 有联系, 类型转换异常! ClassCastException!
3. 存在条件: 继承关系, 方法需要重写,
instanceof关键字
public static void main(String[] args){
// Object > String
// Object > Person > Student
// Object > Person > Teacher
Object obj = new Student();
// 如果X和Y存在父子关系, 那么编译通过, 若不存在父子关系, 则编译报错
// 结果是: new()出来的实际对象与Y进行比较如果存在关系, 则true, 否则false
// System.out.println(X instanceof Y);
System.out.println(obj instanceof Student); // true
System.out.println(obj instanceof Person); // true
System.out.println(obj instanceof Object); // true
System.out.println(obj instanceof Teacher); // false
System.out.println(obj instanceof String); // false
System.out.println("=======================");
Person person = new Student();
System.out.println(person instanceof Student); // true
System.out.println(person instanceof Person); // true
System.out.println(person instanceof Object); // true
System.out.println(person instanceof Teacher); // false
// System.out.println(person instanceof String); // 编译报错
System.out.println("=======================");
Student student = new Student();
System.out.println(student instanceof Student); // true
System.out.println(student instanceof Person); // true
System.out.println(student instanceof Object); // true
// System.out.println(student instanceof Teacher); // 编译报错
// System.out.println(student instanceof String); // 编译报错
System.out.println("=======================");
}
类型转换
public static void main(String[] args){
// 类型之间的转化: 父 子
// 高 低
Person obj = new Student();
// student将这个对象转换为Student类型, 我们就可以使用Student类型的方法了!
// 等于 Student student = new Student(); student.go();
((Student)obj).go();
// 子类转换为父类, 可能丢失属于子类特有的方法!
Student student = new Studnet();
student.go();
Person person = student;
}
类型转换小结
- 父类引用指向子类的对象
- 把子类转换为父类, 向上转型;
- 把父类转换为子类, 向下转型: 强制转型
- 方便方法的调用, 减少重复的代码! 简洁