Java的三大特性
面向对象是 java 的核心思想,面向对象的三大特征:封装、继承、多态。
1 封装
1.1 概念
面向对象的封装可以把对象的属性和方法组合在一起,统一提供对外的访问权限,封装就是将对象的使用者和设计者分开,设计者可以设计出外部可以操作 的内容和只能内部操作的内容。使用者只能使用设计好的内容,却看不见设计者 是如何实现的。就像计算机是由 cpu、内存和各种外设组成的,对于计算机的用 户来说,只能使用这些部件,但是却看不见这些部件的内部结构。
1.2 好处
在程序设计中,类把数据和方法封装到一起,对数据和方法的操作起到了保 护的作用。
1.3 权限修饰符
(1)开发人员在进行封装的时候,需要借助于修饰符来控制对属性和方法的访问
public:表示公共的,用 public 修饰的属性和方法,其他任何的类都可以去 访问,这是最开放的权限。 private:表示私有的,用 private 修饰的属性和方法,只能在当前类中使用, 其他类中没有办法使用。 protected:表示受保护的,用 protected 修饰的属性和方法,可以在本包中的所有类中可以使用,并且可以在非本包的子类中可以是使用。
缺省的:就是方法和属性面前没有任何的修饰符,缺省修饰符的属性和方法 可以在同包中的其他类进行访问,不允许其他包中的类,包括子类进行访问。
public class Person {
//定义属性
private String name;
private boolean sex;
private int age;
private String hobby;
//定义公共的方法
public void display(){
//.....
}
//定义一个私有的方法
private String getSex(){
return sex?"女":"男";
}
//定义一个受保护的方法
protected void study(){
//.....
}
//定义一个缺省的方法
void filter(){
//.....
}
}
(2)修饰符的权限表
(3)注意
- 一般情况下,属性一般用 private 修饰,为了 private 修饰的属性能被外部访问。 通常为属性定义一组 get/set 方法,称为属性的访问器。
- 如果属性只有 get 方法,没有 set 方法,称为只读属性;如果属性只有 set 方法, 没有 get 方法称为只写属性;
- 访问器对外一定要用公共的。
2 继承
被继承的类叫做父类(基类,超类)。 继承的类叫做子类。
2.1 继承的特点
子类继承父类的特征和行为,使得子类具有父类的各种属性和方法。在继承关系中,父类更通用,子类更具体。
(1)子类拥有父类所有的属性和方法(构造方法除外,构造方法只能调用,不能继承);
(2)子类还可拥有自己特有的属性和方法;
(3)子类可以重写父类中已经拥有的方法(普通方法)。
2.2 继承的优点
继承可以有效的实现代码的复用,避免重复的代码的出现。(当两个类具有相同 的特征和行为的时候,可以将相同的部分抽取出来放到一个类中作为父类,让其他的两个类继承这个父类)。
2.3 继承的语法
[修饰符] class 类名 extends** 父类名{
//类的结构体
}
在 java 中用 extends 关键字来表示一个类继承了另一个类。在父类中定义一些通用的方法和属性,子类自动去继承父类的属性和方法(私有的除外)。
◣注意
(1)构造方法可以被子类调用,但是不可以被子类继承。
(2)在 java 中一个类只能有一个直接的父类(单继承),但是间接的可以继承多 个父类。
(3)一个父类可以有很多个子类。
3 多态
3.1 理解多态
不同环境下的多种形态 ,多态在面向对象程序设计中,就是把子类的对象赋值给父类,用父类的引用调用方法的时候,具体执行方法的是子类的对象。在 Java 中有两种形式可以实现多态:一是继承(多个⼦类对同⼀⽅法的重写),二是通过实现接⼝来覆盖接⼝中同⼀⽅法。
3.2 多态的优点
(1)多态可以增强程序的可扩展性以及维护性。
(2)使得代码更加简洁,结构更加清晰。
3.3 多态的使用
多态的语法:
父类名 父类对象名 = new 子类名([参数列表]);
多态的使用:
(1)一般做法:写一个方法,它只接受父类作为参数,编写的代码只和父类打 交道,调用这个方法的时候,实例化不同子类的对象(new 一个对象)。
(2)具体做法 :子类重写父类的方法。 把父类类型作为参数的类型,该父类以及子类对象作为参数传入。 运行的时候,根据实际创建的对象类型动态的决定使用那个方法。
例如:现在要计算多个图像的面积,包括圆形,矩形等,但是每一个图形的计算方式有不同,我们可以使用继承来实现。
(1)定义一个 Shape 类
public class Shape {
/*** 计算图形的面积的方法 */
public double area(){
System.out.println("父类中的方法");
return 0;
}
}
(2)定义两个图形类 Cycle 和 Square,并继承 Shape 类,重写 Shape 类中的 area()方 法
/*** 圆形 */
public class Cycle extends Sharp{
private double r;//半径
public static final double PI=3.14;//π
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
public Cycle(double r) {
this.r=r;
}
/*** 重写父类中的计算面积的方法 */
@Override
public double area(){
double area=PI*r*r;
return area;
}
}
//长方形
public class Square extends Sharp{
private double chang;
private double kuan;
public double getChang() {
return chang;
}
public void setChang(double chang) {
this.chang = chang;
}
public double getKuan() {
return kuan;
}
public void setKuan(double kuan) {
this.kuan = kuan;
}
public Square(double chang, double kuan) {
super();
this.chang = chang;
this.kuan = kuan;
}
//重写父类中的计算面积的方法
@Override public double area() {
double area=chang*kuan;
return area;
}
}
(3)编写测试类
//多态
public class Test {
/*多态:将子类的引用(内存地址)赋值给父类对象, 使用父类对象调用方法的时候其实调用的是子类重写后或者继承过来的父类的方法的方法。 */
//计算图形的面积
public static void main(String[] args) {
//创建子类的对象并将子类的对象赋值给父类(多态)
Sharp sharp=new Cycle(5);
double area=sharp.area();
System.out.println(area);
Sharp sharp2=new Square(4, 5);
double area1=sharp2.area();
System.out.println(area1);
}
}
4 方法的重写与重载
4.1 方法的重写
重写发⽣在运⾏期,在子类中可以重新的定义父类中的属性,重写父类中的方法可以获得与父类不同的功能。
重写条件
- 方法名必须相同;
- 访问权限的修饰符范围在重写的时候不能被缩小,只能是相等或者扩大;
- 方法的返回类型必须一致;
- 方法的参数列表必须一样,包括数量和数据类型,参数名称没有要求;
- 用 final 修饰的方法不能够被重写(覆盖)。
例如:父类中的方法
public void eat(String nameq){
System.out.println(name+"在吃东西");
}
子类中重写的方法
//方法的重写
@Override //用来检查方法是否重写正确
public void eat(String name){
System.out.println(getName()+"在吃老鼠");
}
4.2 方法的重载
概念:在同一个类中一个方法名可以定义很多个方法,只要参数不同即可,这叫做方法的重载。
好处:加强方法的灵活性;有利于方法调用的方便性。
重载条件:
- 方法名称相同;
- 方法的参数不同,其中方法的参数不同包括:(数量类型不同的不同);
- 相同数量的参数中,不同参数类型在方法参数列表中的顺序不同。
- 注意 方法重载与方法的返回值类型和方法的修饰符没有任何关系,与参数列表中的参数名称也没有任何的关系,也就是⽅法返回值和访问修饰符可以不同。
/*** 方法的重载 */
public class Sum {
//计算两个整数相加
public int add(int a,int b){
return a+b;
}
public double add(double a,double b){
return a+b;
}
public long add(long a,long b){
return a+b;
}
}