java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > JAVA中方法的声明及使用

JAVA中方法的声明及使用方式(继承、多态、封装)

作者:小新的编程之路

这篇文章主要介绍了JAVA中方法的声明及使用方式(继承、多态、封装),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、写在前面

今天就来总结一下JAVA中方法的声明及使用,即继承、多态、封装。

其实关于三大特性对于学习JAVA的同学来说都是基本的了,毕竟只要接触Java这些都是先要认识的,接下来就系统总结一下。

二、继承

先来说说继承,所谓继承本质就是实现代码的复用,防止重复的代码多次书写,当一个类继承一个类的时候,该类中就会拥有另外一个类中的所有代码

2.1 继承的注意事项

只支持单继承,即一个子类只允许有一个父类,但是可以实现多级继承,及子类拥有唯一的父类,而父类还可以再继承。

子类可以拥有父类的属性和方法。

子类可以拥有自己的属性和方法。

子类可以重写覆盖父类的方法。

2.2 继承的特点

2.3 继承的使用

1,在父子类关系继承中,如果成员变量重名,则创建子类对象时,访问有两种方式。

a:直接通过子类对象访问成员变量

List item

等号左边是谁,就优先使用谁,如果没有就向上找。

b:间接通过成员方法访问成员变量

该方法属于谁,谁就优先使用,如果没有就向上找。

public class FU {
    int numFU = 10;
    int num = 100;
    public void method(){
        System.out.println("父类成员变量:"+numFU);
    }
    public void methodFU(){
        System.out.println("父类成员方法!");
    }
}
public class Zi extends FU{
    int numZi = 20;
    int num = 200;
    public void method(){
        System.out.println("子类成员变量:"+numFU);
    }
    public void methodZi(){
        System.out.println("子类方法!");
    }
}
public class ExtendDemo {
    public static void main(String[] args) {
        FU fu = new FU();
        // 父类的实体对象只能调用父类的成员变量
        System.out.println("父类:" + fu.numFU);   // 结果:10
        
        Zi zi = new Zi();
        System.out.println("调用父类:" + zi.numFU); // 结果:10
        System.out.println("子类:" + zi.numZi);   // 结果:20
 
        /** 输出结果为200,证明在重名情况下,如果子类中存在则优先使用,
         *  如果不存在则去父类查找,但如果父类也没有那么编译期就会报错。
         */
        System.out.println(zi.num); // 结果:200
        /**
         * 通过成员方法调用成员变量
         */
        zi.method();    // 结果:10
    }
}

2,同理:

​ 成员方法也是一样的,创建的对象是谁,就优先使用谁,如果没有则直接向上找。

​ 注意事项:

​ 无论是成员变量还是成员方法,如果没有都是向上父类中查找,绝对不会向下查找子类的。

3,在继承关系中,关于成员变量的使用:

int numZi = 10;
 public void method() {
   int numMethod = 20;
   System.out.println(numMethod);  // 访问局部变量
   System.out.println(this.numZi); // 访问本类成员变量

2.4 重写和重载

2.4.1 重写(override)

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。

即外壳不变,核心重写!

class Animal{
   public void move(){
      System.out.println("动物行走!");
   }
}
 
class Dog extends Animal{
   public void move(){
      System.out.println("狗可以跑和走");
   }
}
 
public class TestDog{
   public static void main(String args[]){
      Animal a = new Animal(); // Animal 对象
      Animal b = new Dog(); // Dog 对象
      a.move();// 执行 Animal 类的方法
      b.move();//执行 Dog 类的方法
   }
}

重写的规则:

1,参数列表必须与被重写方法相同。

2,访问权限不能比父类中被重写的方法的访问权限更低(public>protected>(default)>private)。

3,父类成员的方法只能被它的子类重写。

4,被final修饰的方法不能被重写。

5,构造方法不能

2.4.2 重载(overload)

重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

​ 最常用的地方就是构造器的重载。

   public class Overloading {
       public int test(){
           System.out.println("test1");
           return 1;
       }
       public void test(int a){
           System.out.println("test2");
       }   
       //以下两个参数类型顺序不同
       public String test(int a,String s){
           System.out.println("test3");
           return "returntest3";
       }   
       public String test(String s,int a){
           System.out.println("test4");
           return "returntest4";
       }    
       public static void main(String[] args){
           Overloading o = new Overloading();
           System.out.println(o.test());
           o.test(1);
           System.out.println(o.test(1,"test3"));
           System.out.println(o.test("test4",1));
       }
   }

重载规则:

1,被重载的方法必须改变参数列表(参数个数或者类型不一样)。

2,被重载的方法可以改变返回类型。

3,被重载的方法可以改变访问修饰符。

2.4.3 this,super关键字

super()关键字的用法:

this关键字用法:

​ 注意:

this关键字同super一样,必须在构造方法的第一个语句,且是唯一的。

this与super不能同时存在。

2.4.4 补充概念

隐藏

父类和子类拥有相同名字的属性或者方法( 方法隐藏只有一种形式,就是父类和子类存在相同的静态方法)时,父类的同名的属性或者方法形式上不见了,实际是还是存在的。

隐藏是对于静态方法和成员变量(静态变量和实例变量)而言的

public class Animal {
    String name;
    int age;
    int legs;
    public void eat(){
        System.out.println("动物要吃饭");
    };
    //类方法,静态方法
    //通过类就可以直接调用
    public static void run(){
        System.out.println("动物在奔跑");
    }
}
public class Cat extends Animal {
    //重写父类方法
    public void eat() {
       System.out.println("小猫吃鱼");
    }
    //隐藏父类的run方法
    public static void run(){
        System.out.println("小猫在奔跑");
    }

}

对象转型

引用类型和对象类型不一致的情况下的转换问题

子类转父类(向上转型)

Animal a = new Animal();
Cat c = new Cat();
a = c;

一个很简单的判别办法,把右边的当做左边来用,看说得通不。右边c引用所指向的对象的类型是 猫

左边a引用的类型是 普通动物,把猫 当做 普通动物,说不说得通? 说得通,就可以转

父类转子类(向下转型)

父类转子类,有的时候行,有的时候不行,所以必须进行强制转换。强制转换的意思就是 转换有风险,风险自担。

可以的情况

Animal a = new Animal();
Cat c = new Cat();
a = c;
c = (Cat) a;
不可以的情况

Animal a = new Animal();
Cat c = new Cat();
Dog d = new Dog();
a = d;
c = (Cat) a;
没有继承关系的两个类,互相转换

没有继承关系的两个类,互相转换,一定会失败。

虽然Cat和Dog都继承了Animal,但是彼此没有互相继承关系

构造器

子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。

如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。

如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

三、多态

3.1 定义和优点

定义:

优点:

3.2 多态的体现形式

继承父类引用指向子类重写

注意:在多态中,编译看左边,运行看右边

   public class MultiDemo {
       public static void main(String[] args) {
           // 多态的引用,就是向上转型
           Animals dog = new Dog();
           dog.eat();
           
           Animals cat = new Cat();
           cat.eat();
           
           // 如果要调用父类中没有的方法,则要向下转型
           Dog dogDown = (Dog)dog;
           dogDown.watchDoor();
   
       }
   }
   class Animals {
       public void eat(){
           System.out.println("动物吃饭!");
       }
   }
   class Dog extends Animals{
       public void eat(){
           System.out.println("狗在吃骨头!");
       }
       public void watchDoor(){
           System.out.println("狗看门!");
       }
   }
   class Cat extends Animals{
       public void eat(){
           System.out.println("猫在吃鱼!");
       }
   }

例如:

在设计房子时,大门的设计应该开进不同型号车辆,如打开一扇门,可以开进摩托车;打开两扇门,可以开进小汽车;如果需要,打开三扇门,允许开进货车等。

同样是门,由于不同参数,可以完成不同的功能,这个门具有多态性。

3.3 向上转型

四、封装

4.1 封装的特性

在面向对象程式设计方法中,封装(Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问;要访问该类的代码和数据,必须通过严格的接口控制;封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段;适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。 

封装的特点

4.2 封装的实现

使用private修饰符,表示最小的访问权限。

对成员变量的访问,统一提供setXXX,getXXX方法。

下面请看一个Student实体对象类:

public class Student implements Serializable {
    
    private Long id;
    private String name;
    private Integer sex;
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Integer getSex() {
        return sex;
    }
 
    public void setSex(Integer sex) {
        this.sex = sex;
    }
}

分析:对于上面的一个实体对象,我想大家都已经很熟悉了。将对象中的成员变量进行私有化,外部程序是无法访问的。但是我们对外提供了访问的方式,就是set和get方法。

​ 而对于这样一个实体对象,外部程序只有赋值和获取值的权限,是无法对内部进行修改,因此我们还可以在内部进行一些逻辑上的判断等,来完成我们业务上的需要。

​ 到这里应该就明白封装对于我们的程序是多么重要。下面再来说说继承的那点事。

修改属性的可见性来限制对属性的访问(一般限制为private),例如

```java
public class People {
//将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
    private String name;
    private int age;
}

对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:

public class People{
    //采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
    private String name;
    private int age;
​
    public String getName(){
        return name;
    }
​
  
    public void setName(String name){
        this.name = name;
    }
}

4.3 成员的访问权限

Java提供了三个访问控制符:private、protected和public,分别代表三个访问控制级别。

default访问控制权限(包访问权限)

如果类里的一个成员不使用任何访问控制符修饰,则使用default默认访问控制,default访问控制的成员可以被相同包下其他类访问。

protected访问控制权限(子类访问权限)

如果一个成员使用protected访问控制符修饰,那么这个成员即可以被同一包中其他类访问,也可以被不同包中的子类访问。

public访问控制权限(公共访问权限)

如果一个成员使用public访问控制符修饰,则可以被所有类访问。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文