Java从入门到精通五(Java面向对象下,封装,继承,多态)

简介: 1:封装的概念在程序设计中,封装是一种将数据实现包装,隐藏起来的方法。数据是非常重要的,封装的出现,提高了数据的安全性。不能通过直接去访问数据,只能用程序中提供的可访问数据的接口。另外一点,就是通过封装,让我们更加方便的去访问自己所存储的数据,还有就是便于维护。

一:封装(Encapsulation)


1:封装的概念


在程序设计中,封装是一种将数据实现包装,隐藏起来的方法。数据是非常重要的,封装的出现,提高了数据的安全性。不能通过直接去访问数据,只能用程序中提供的可访问数据的接口。另外一点,就是通过封装,让我们更加方便的去访问自己所存储的数据,还有就是便于维护。


2:封装实现的过程


<1>修改类属性

常见的修改就是修改类中定义变量的访问权限。我们用private关键字修饰。被private修饰的属性只能被本类访问,其它的类是无法直接访问的,注意并不是不能访问。


对类属性的权限private化


package java_practice;
public class Student {
    private String name;
    private int age;
}


name,age都用private关键字修饰,使得name,age只能被本类访问。其它的外部类是不能访问的。这样相当于对外部类隐藏了属性,使得对属性的访问具有了一定的限制。


<2>提供接口


这里的接口是提供给外部类访问程序的接口。是两个方法。get(),set(),get()用于获取到值,set()用于对属性赋值。


具体如下示例


package java_practice;
public class Student {
    private String name;
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}


这样就基本实现了一个简单的封装。


3:外部类通过提供方法访问权限属性

上代码举例


package java_practice;
public class Student_Test {
    public static void main(String args[])
    {
        Student s = new Student();//创建Student类的对象
        s.setAge(18);
        s.setName("li");
        System.out.println(s.getName()+"今年"+s.getAge()+"岁");
    }
}


输出结果:



可以看到这样就可以正常访问了。


4既然接口都给了,封装还有什么意义?还不是可以访问?


可能你有这样的疑惑,特别是对于刚学的小白来说,不明白这样的意义。但是事实上并不是这样的,我们粉装的意义就是权限,是访问的限制规定,而不是禁止。当然你可以禁止,但是如果是禁止的话,也就没必要提供接口方法了。


怎么体现?我们还拿上段代码举例。我们可以在Student类中的set方法设置一些限定,以限制测试主类的属性的不恰当的修改。


来看代码


package java_practice;
public class Student {
    private String name;
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if(age<0||age>200)
        {
            System.out.println("赋值不合理");
        }
        System.exit(0);//甚至你可以直接退出
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}


然后测试类这样做了


package java_practice;
public class Student_Test {
    public static void main(String args[])
    {
        Student s = new Student();//创建Student类的对象
        s.setAge(201);
        s.setName("li");
        System.out.println(s.getName()+"今年"+s.getAge()+"岁");
    }
}

输出



你看,这样就对访问修改做了限制。当然你也可以这样。对get()方法里面进行操作。让用户传入参数,判断参数是否与你设定的一样,如果不一样,那就拒绝让外部类获取到值。这样就类似了一种口令。


二:继承(inheritance)


1:继承的概念


在程序设计中,面向对象也包含了继承这么一种设计理念。java中实现了类的继承,被继承的类叫做父类,继承的类叫子类。子类可以拥有父类的某些属性,注意是某些,不是全部。


继承的方式有多种,单继承,多继承,多重继承。java是不支持多继承的。也就是说,你一个子类不能继承多个父类,但是多个子类可以继承同一个父类。


2: 单继承


单继承很好理解,就是只有一个子类直接继承,子类没有被其它类继承。


//父类
package java_practice;
public class Student {
    private String name;
    private int age;
    public String place;
    static int number = 666;
    public int getAge() {
        return age;
    }
    public void describe()
    {
        System.out.println("学生:"+name_1);
    }
    public void setAge(int age) {
        if(age<0||age>200)
        {
            System.out.println("赋值不合理");
        }
        System.exit(0);//甚至你可以直接退出
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//子类
package java_practice;
public class Studen_1 extends Student{
    public static void main(String args[])
    {
        System.out.println(number);//父类的number没有被private修饰
        //System.out.println(name);name没有被拥有,所以无法输出
        Student s = new Student();
        System.out.println(s.getName());//如果要访问,只能用提供的接口方法
    }
}


子类可以直接访问父类的共有变量这些属性,那么方法是怎么访问呢?对于一般的方法的访问方法


我们在分类写一个一般的共有方法,子类可以拥有这个属性。


子类调用父类的一般方法(当然该方法也被子类所拥有)


package java_practice;
public class Studen_1 extends Student{
    public static void main(String args[])
    {
        System.out.println(number);//父类的number没有被private修饰
        //System.out.println(name);
        Student s = new Student();
        System.out.println(s.getName());
        Studen_1 s1 = new Studen_1();
        s1.describe();//子类通过对象调用方法
    }
}

 

子类的继承父类的时候必须用做的那些事情。


必须调用父类的构造函数,如果父类有默认的构造函数,子类实例化会自动调用,如果父类没有声明默认的构造函数的话(无形参构造函数),子类构造函数必须通过super调用父类的构造函数。另外需要注意的是,子类构造函数必须通过super调用父类的构造函数。


在new()对象的时候,父类中的构造函数就会自动执行。


我在父类中写了一个无参构造方法


//父类
package java_practice;
public class Student {
    private String name;
    private int age;
    public String place;
    static int number = 666;
    String name_1 = "jgdabc";
    public Student(){
        System.out.println("Hello");
    }
    public void describe()
    {
        System.out.println("学生:"+name_1);
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if(age<0||age>200)
        {
            System.out.println("赋值不合理");
        }
        System.exit(0);//甚至你可以直接退出
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//子类
package java_practice;
public class Studen_1 extends Student{
    public static void main(String args[])
    {
        System.out.println(number);//父类的number没有被private修饰
        //System.out.println(name);
        Student s = new Student();
        System.out.println(s.getName());
        Studen_1 s1 = new Studen_1();
        s1.describe();
    }
}


我们看执行结果



可以看到父类这个无参构造方法执行了两次。所以说,每一次new对象的时候这个无参构造方法会自动执行。


那么对于父类的有参构造方法呢?我们还是来看代码。我们在父类中写一个有参构造函数,将父类的无参覆盖掉。如果父类只有有参构造方法,那么子类必要用super关键字进行实现。我们需要这样做。看示例代码


//父类
package java_practice;
public class Student {
    private String name;
    private int age;
    public String place;
    static int number = 666;
    String name_1 = "jgdabc";
    /*public Student(){
        System.out.println("Hello");
    }*/
    public void describe()
    {
        System.out.println("学生:"+name_1);
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if(age<0||age>200)
        {
            System.out.println("赋值不合理");
        }
        System.exit(0);//甚至你可以直接退出
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//子类
package java_practice;
public class Studen_1 extends Student{
    public Studen_1(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public static void main(String args[])
    {
        System.out.println(number);//父类的number没有被private修饰
        //System.out.println(name);
        Studen_1 s = new Studen_1(18);
        s.describe();
    }
}



说明一下,父类的构造器是不能被子类继承的。子类默认继承父类的属性和方法,但不会继承父类的构造器,而是在子类被实例化时会默认调用父类的空构造器。子类在创建的时候会调用自己的空构造器,并在空构造器会隐式调用super(),即父类的空构造器。如果父类的构造器被重载,那么子类中的构造器也必须初始化父类的构造器,否则会报编译错误。


3: 多重继承


多重继承指的是什么


假如一个Student类作为父类,那么一个Student1类可以继承Student,Student2继承Student1。以此类推,但是你不能Student2既继承Student又继承Student1。


那么多重继承有什么特点呢?


我们还是代码举例说明


package java_practice;
public class Student {
    private String name;
    private int age;
    public String place;
    static int number = 666;
    String name_1 = "jgdabc";
    public Student(int age)
    {   this.age = age;
        System.out.println("我今年"+age+"岁");
    }
    // public Student(){
    //     System.out.println("Hello");
    // }
    public void describe()
    {
        System.out.println("学生:"+name_1);
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if(age<0||age>200)
        {
            System.out.println("赋值不合理");
        }
        System.exit(0);//甚至你可以直接退出
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
package java_practice;
public class Studen_1 extends Student{
    public Studen_1(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public static void main(String args[])
    {
        System.out.println(number);//父类的number没有被private修饰
        //System.out.println(name);
        Studen_1 s = new Studen_1(18);
    }
}
package java_practice;
public class Student2 extends Studen_1 {
    public Student2(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public static void main(String args[]){
        Student2 s2 = new Student2(19);
        s2.describe();
    }
}



可以看到多重继承的类依然可以访问其父类的父类的方法,也同样需要调用好有参构造器(直接父类的有参构造器)(父类的无参被有参覆盖掉。需要我们手动调用)同样也具有同样的非公有属性。


4:多个子类继承继承同一个父类

package java_practice;
public class Student2 extends Studen_1 {
    public Student2(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public static void main(String args[]){
        Student2 s2 = new Student2(19);
        s2.describe();
    }
}
package java_practice;
public class Student3 extends Student {
    public Student3(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public static void main()
    {
    }
}


三:多态(polymorphism)


1:多态的概念


多态是java面向对象的另外一个特征


简明的说,就是一个行为的不同表现形式。如何理解。比如说吃饭的的行为,你吃饭和别人吃饭的动作肯定是和别人多多少少都有不同表现的,那么这个就是多态。


2:实现多态的过程


1:实现继承(上述已经说明,不再赘述)

2:实现方法重写(一般方法)


注意:方法重写和方法重载是不一样的


首先说方法重载,简单就是一个类中多个同名方法,但是参数列表不一样(参数个数或者参数的类型)

而重写发生在继承关系,子类对父类的一般方法进行重写,参数列表以及方法名必须一致,然后内部的行为不一样。


举例一个方法重写的例子


同样给出父类和子类,我们对父类的describe()方法进行重写


//父类
package java_practice;
public class Student {
    private String name;
    private int age;
    public String place;
    static int number = 666;
    String name_1 = "jgdabc";
    public Student(int age)
    {   this.age = age;
        System.out.println("我今年"+age+"岁");
    }
    // public Student(){
    //     System.out.println("Hello");
    // }
    public void describe()
    {
        System.out.println("学生:"+name_1);
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if(age<0||age>200)
        {
            System.out.println("赋值不合理");
        }
        System.exit(0);//甚至你可以直接退出
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//子类
package java_practice;
public class Studen_1 extends Student{
    public Studen_1(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public void describe()
    {
        System.out.println("Long long ago!");
    }
    public static void main(String args[])
    {
        System.out.println(number);//父类的number没有被private修饰
        //System.out.println(name);
        Studen_1 s = new Studen_1(18);
        s.describe();
    }
}


实现多个子类重写父类相同的方法,便很生动的体现了多态。



可见子类重写父类的一般方法后,当子类再次调用这个方法就会调用到重写后的这个方法

3:对父类的引用指向子类对象(我们又可称为向上转型)

下面举一个例子。


package java_practice;
public class Student {
    private String name;
    private int age;
    public String place;
    static int number = 666;
    String name_1 = "jgdabc";
    public Student(int age)
    {   this.age = age;
        System.out.println("我今年"+age+"岁");
    }
    public Student() {
    }
    // public Student(){
    //     System.out.println("Hello");
    // }
    public void describe()
    {
        System.out.println("学生:"+name_1);
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if(age<0||age>200)
        {
            System.out.println("赋值不合理");
        }
        System.exit(0);//甚至你可以直接退出
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
package java_practice;
public class Studen_1 extends Student{
    public Studen_1(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public Studen_1() {
    }
    public void describe()
    {
        System.out.println("Long long ago!");
    }
}
package java_practice;
public class Student2 extends Studen_1 {
    public Student2(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public Student2() {
    }
    public void describe()
    {
        System.out.println("no body but you!");
    }
}
package java_practice;
public class Student3 extends Student {
    public Student3(int age) {
        super(age);
        //TODO Auto-generated constructor stub
    }
    public Student3() {
    }
    public void describe()
    {
        System.out.println("Believe you self!");
    }
}
package java_practice;
public class test {
       public static void main(String args[])
    {
        Student s = new Studen_1();//向上转型
        s.describe();
        Studen_1 s1 = new Studen_1();//进行向下转型
        s1.describe();
        show(new Student2());
        show(new Student3());
    }
    public static void show(Student a)
    {
        if(a instanceof Studen_1)
        {
            Studen_1 s1 = (Studen_1) a;
            s1.describe();
        }else if (a instanceof Student2)
        {
            Student2 s2 = (Student2)a;
            s2.describe();
        }else if (a instanceof Student3)
        {
            Student3 s3 = (Student3)a;
            s3.describe();
        }
    }
}


首先定义一个Student主类,Student_1继承Student,Student_2继承Student_1,Student_3继承Student2,然后我们再定义一个测试类,在测试类中进行具体对象的实现,并展示多态的效果。



我们也可以完全将父类写成一个抽象类,然后对抽象类中的属性或者方法进行具体的实现。


相关文章
|
2月前
|
人工智能 Java 编译器
Java:面向对象
本文介绍了Java编程中的核心概念,包括包的命名规范与自动导入机制、构造方法的特点与使用、`this`和`super`关键字的作用、继承的基本规则、访问权限的设置、封装的意义、多态的实现原理以及`static`关键字的用法。通过详细解析每个知识点,并结合代码示例,帮助读者深入理解Java面向对象编程的核心思想与实践技巧。内容适合初学者及进阶开发者学习参考。
|
4月前
|
缓存 安全 Java
java面试-基础语法与面向对象
本文介绍了 Java 编程中的几个核心概念。首先,详细区分了方法重载与重写的定义、发生阶段及规则;其次,分析了 `==` 与 `equals` 的区别,强调了基本类型和引用类型的比较方式;接着,对比了 `String`、`StringBuilder` 和 `StringBuffer` 的特性,包括线程安全性和性能差异;最后,讲解了 Java 异常机制,包括自定义异常的实现以及常见非检查异常的类型。这些内容对理解 Java 面向对象编程和实际开发问题解决具有重要意义。
|
3月前
|
Java 编译器 程序员
java中重载和多态的区别
本文详细解析了面向对象编程中多态与重载的概念及其关系。多态是OOP的核心,分为编译时多态(静态多态)和运行时多态(动态多态)。编译时多态主要通过方法重载和运算符重载实现,如Java中的同名方法因参数不同而区分;运行时多态则依赖继承和方法重写,通过父类引用调用子类方法实现。重载是多态的一种形式,专注于方法签名的多样性,提升代码可读性。两者结合增强了程序灵活性与扩展性,帮助开发者更好地实现代码复用。
142 0
|
4月前
|
人工智能 JSON Java
列表结构与树结构转换分析与工具类封装(java版)
本文介绍了将线性列表转换为树形结构的实现方法及工具类封装。核心思路是先获取所有根节点,将其余节点作为子节点,通过递归构建每个根节点的子节点。关键在于节点需包含 `id`、`parentId` 和 `children` 三个属性。文中提供了两种封装方式:一是基于基类 `BaseTree` 的通用工具类,二是使用函数式接口实现更灵活的方式。推荐使用后者,因其避免了继承限制,更具扩展性。代码示例中使用了 Jackson 库进行 JSON 格式化输出,便于结果展示。最后总结指出,理解原理是进一步优化和封装的基础。
|
5月前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。
|
5月前
|
安全 网络协议 Java
Java网络编程封装
Java网络编程封装原理旨在隐藏底层通信细节,提供简洁、安全的高层接口。通过简化开发、提高安全性和增强可维护性,封装使开发者能更高效地进行网络应用开发。常见的封装层次包括套接字层(如Socket和ServerSocket类),以及更高层次的HTTP请求封装(如RestTemplate)。示例代码展示了如何使用RestTemplate简化HTTP请求的发送与处理,确保代码清晰易维护。
|
6月前
|
Java
Java 面向对象编程的三大法宝:封装、继承与多态
本文介绍了Java面向对象编程中的三大核心概念:封装、继承和多态。
407 15
|
7月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
91 1
|
Java 开发者
Java 面向对象新视界:揭秘子类如何“继承”父类精华,再添“创新”之笔
【6月更文挑战第16天】在Java的面向对象世界,子类继承父类的特性,如`Circle`继承`Shape`,展示“is-a”关系。子类不仅保留父类的`color`和`display`方法,还添加了`radius`属性及定制的显示逻辑。这种继承与创新允许代码复用,增强灵活性和可扩展性,使得构建复杂系统变得更加高效和模块化。通过持续的继承与定制,开发者能构建出一系列独具特色的类,充分展现面向对象编程的力量。
199 57
|
Java 编译器
Java面向对象(三)详解: 封装 | 继承 | 方法重写 | 抽象类
Java面向对象(三)详解: 封装 | 继承 | 方法重写 | 抽象类
178 2

热门文章

最新文章