三大特性
封装
一句话:属性私有化,get/set
在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
优点
提高程序的安全性,保护数据。
隐藏信息,实现细节。
统一接口
减少耦合。
实现封装
修改属性的可见性来限制对属性的访问(一般限制为private), 只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问
public class Student { private int age;// 年龄 private String name;// 名字 // 提供一些public 的get、set方法。 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if (age > 100 || age < 0) { this.age = 3; } else { this.age = age; } } }
采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
public class Application { public static void main(String[] args) { Student student = new Student(); //student.name; // private私有化之后,外部类无法访问该属性。 student.setName("小明"); student.setAge(18); // 年龄在内部处理逻辑 // student.setAge(999); //处理不合理的年龄 String name = student.getName(); int age = student.getAge(); System.out.println(name + age +"岁啦"); } }
以上实例中public方法是外部类访问该类成员变量的入口。
通常情况下,这些方法被称为getter和setter方法。
因此,任何要访问类中私有成员变量的类都要通过这些getter和setter方法。
继承
一句话:子类继承父类的特征和行为。
extends 是"扩展"的意思,子类是父类的扩展。
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
特性
子类拥有父类非 private 的属性、方法。
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。(重写)
Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
关键字
继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,
当一个类没有继承的两个关键字,则默认继承object祖先类(这个类在 java.lang 包中,所以不需要 import)。
extends:在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
implements:可以同时继承多个接口(接口跟接口之间采用逗号分隔),使java具有多继承的特性。
public interface A { public void eat(); public void sleep(); } public interface B { public void show(); } public class C implements A,B { }
super:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this:指向自己的引用。
final :声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:
区别 | 前提 | 构造方法 | |
---|---|---|---|
this | 表示本身调用者这个对象 | 没有继承也可以使用 | this() |
super | 代表父类对象的引用 | 只能在继承条件才可以使用 | super() |
注意点
super()调用父类的构造方法,必须在构造方法的第一个
this()调用自己的构造方法,必须在构造方法的第一个,所以this() super() 不能同时出现
super()只能出现在子类的方法或构造方法中!
继承格式
class 父类 { } class 子类 extends 父类 { }
父类Person
/** * 隐式继承Object类 */ public class Person { private String name; public void say() { System.out.println("说话说话"); } }
子类Student继承Person
public class Student extends Person { }
public class Application { public static void main(String[] args) { Student student = new Student(); student.say(); } }
子类继承了父类的公共方法和属性
继承类型
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等
IDEA快捷键 ctrl + H 查看继承关系
方法重写
重写都是方法的重写,与属性无关
重写:需要有继承关系,子类重写父类的非静态方法!
方法名必须相同
参数列表必须相同
修饰符可以扩大但不能缩小 public >protected>default>private
抛出的异常范围:可以被缩小但不能扩大;
为什么需要重写?父类的功能,子类不一定需要,或者不一定满足。
多态
一句话:同一个方法可以根据发送对象的不同而采取多种不同的行为方式。
使用手机扫描二维码支付时,二维码并不知道客户是通过何种方式进行支付,只有通过二维码后才能判断是走哪种支付方式执行对应流程。
多态可以实现动态编译:类型在执行过程中才可以确定:增强可扩展性~
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作。
前提条件
继承
重写
父类引用指向子类
特征
对象能执行的方法和左边的类型有关,和右边的关系不大
子类能调用的方法都是自己的或者继承父类的。
父类型可以指向子类,但是不能调用子类独有的方法。
父类想要执行子类的方法需要向下转型,高转低是强制转换!
优点
减耦合
增强可以替换性
可扩展性
灵活性等
关键词instanceof
instanceof:测试它左边的对象是否是它右边的类的实例
判断一个对象是什么类型,instanceof可以判断两个类之间是否存在父子关系
public class Application { public static void main(String[] args) { // instanceof // 1.先判断左侧的引用类型与右边类是否有关系 // 2.再判断左侧的实际类型与右边类是否有关系 // 继承关系 // Object // / \ // String Person // / \ // Student Teacher // 公式 ClassA obj = new ClassB(); // obj instanceof 任意类 // 能够通过编译 取决于ClassA 与 任意类 有没有关系 // true/false 取决于ClassB 与 任意类 有没有关系 // 对象的引用类型是Student类 Student obj1 = new Student(); System.out.println("=======Student->Student=========="); System.out.println(obj1 instanceof Student); System.out.println(obj1 instanceof Person); System.out.println(obj1 instanceof Object); // System.out.println(obj1 instanceof Teacher); // Student 和 Teacher 是兄弟关系,报错~ // System.out.println(obj1 instanceof String); // Student 与 String无直接联系,报错! Person obj2 = new Student(); System.out.println("=======Person->Student=========="); System.out.println(obj2 instanceof Student); System.out.println(obj2 instanceof Person); System.out.println(obj2 instanceof Object); System.out.println(obj2 instanceof Teacher); // obj2 指向的是Student类,与Teacher无直接联系 //System.out.println(obj2 instanceof String); // Person 与 String无直接联系,报错! Object obj3 = new Student(); System.out.println("=======Object->Student=========="); System.out.println(obj3 instanceof Student); System.out.println(obj3 instanceof Person); System.out.println(obj3 instanceof Object); System.out.println(obj3 instanceof Teacher); System.out.println(obj3 instanceof String); Person obj4 = new Person(); System.out.println("=======Person->Person=========="); // System.out.println(obj4 instanceof Student); System.out.println(obj4 instanceof Person); System.out.println(obj4 instanceof Object); System.out.println(obj4 instanceof Teacher); // System.out.println(obj4 instanceof String); // Person 与 String无直接联系,报错! } }
类型转换
基础类型转换
低 ------>高 隐式转换
高------->低 强制转换
引用类型转换
低(子类)----->高(父类)
低转高:Person obj1 = new Student(); 即向上转换,不需要强制转换
高转低 Student obj2 = (Student)obj1; 即向下转换,需要强制转换
注意:之前学习继承的时候说,子类是父类的扩展,所以子类转换成父类时会丢失一些本身的方法或属性。
父类型可以指向子类,但是不能调用子类独有的方法。因为子类独有的方法丢失了,无法调用。
多态小结
多态是方法的多态,属性没有多态
父类和子类
有联系。instanceof
类型转换异常!ClassCastException!
子类转换成父类,向上转型,丢失方法
父类转换成子类,向下转型 (强制转换)
存在条件
继承关系
方法需要重写
父类引用指向子类对象!
不能重写的方法
static 静态方法属于类,不属于实例
final常量修饰不能继承
private 方法私有
OOP面向对象的编程思想就是抽象
!
[代码区](# 多态代码)
多态代码
第一种情况 对象的实际类型确定,指向的引用类型不确定(可以用父类引用类型指向子类对象)
如下有Person类
Person.java
public class Person { public void say() { System.out.println("father---say"); } }
Student.java
// 继承 Person 类 public class Student extends Person { }
有继承关系才可以指向
Application.java
/** * 测试多态的表现 */ public class Application { public static void main(String[] args) { // 一个对象的实际类型是确定的 // new Student(); // 创建出一个学生 // new Person(); // 创建出一个人 // 可以指向的引用类型就不确定了 Student s1 = new Student(); // new 一个学生 名字叫 学生 Person s2 = new Student();// new 一个学生 名字叫 人(学生也是人,他继承了人) Object s3 = new Student(); s2.say(); } }
运行结果
father---say
子类能调用的方法都是自己的或者继承父类的。如果子类中没有say方法,则调用继承于父类的say方法。
如果在子类重写了父类的say方法,则调用本身的say方法。如下代码重写了父类的say方法:
Student.java
public class Student extends Person { @Override public void say() { // 重写父类say方法 System.out.println("son ---- say"); } }
Application.java
/** * 测试多态的表现 */ public class Application { public static void main(String[] args) { // 一个对象的实际类型是确定的 // new Student(); // 创建出一个学生 // new Person(); // 创建出一个人 // 可以指向的引用类型就不确定了 Student s1 = new Student(); // new 一个学生 由 学生 Person s2 = new Student();// new 一个学生 由人接收(学生也是人,他继承了人) Object s3 = new Student(); s1.say();// 学生 说 s2.say();// 学生 说 } }
运行结果
son ---- say son ---- say
因为实例是确定的,s1,s2都是new 出来的Student()实例对象,方法的功能与实例的实现有关。
如果在Student类中添加一个eat()方法
public class Student extends Person { @Override public void say() { System.out.println("son ---- say"); } public void eat() { System.out.println("son ---- eat"); } }
public class Application { public static void main(String[] args) { Student s1 = new Student(); Person s2 = new Student(); //对象能执行的方法和左边的类型有关,和右边的关系不大 s1.say();// 学生 说 s2.say();// 学生 说 s1.eat(); // s1 左边是学生类,学生类里面有say方法。成功调用 //s2.eat(); // s2 左边是人类,人类中没有eat方法,又不能继承,所以调用失败 } }
对象能执行的方法和左边的类型有关,涉及到类型转换,高-->低 会丢失精度。比如
public class Test { public static void main(String[] args) { float a = 1.5f; long b = 99999999999999L; System.out.println((int)a); // 结果打印1 丢失了小数部分 System.out.println((int)b); // 结果打印276447231 丢失数据溢出部分 } }
但在学习继承的时候知道,子类继承父类获取父类的非私有属性和方法,子类是父类的扩展。
这里引用类型和基本类型的转换是存在区别的,基本类型高精度转型为低精度会丢失数据。而引用类型子类转型为父类会丢失方法或属性。
原文链接:https://www.cnblogs.com/1101-/p/12882780.html
本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。
还没有评论,来说两句吧...