zoukankan      html  css  js  c++  java
  • java中面向对象的三大特性小结

    java中面向对象的三大特性:封装、继承、多态

    封装

    把抽象的数据和对数据的操作封装在一起,隐藏变量的实现细节。数据被保护在内部,程序的其他部分只有通过被授权的操作(成员方法)才能对数据进行访问。

    1、原则

    • 将不需要对外提供的内容都隐藏起来
    • 把属性都隐藏,提供公共方法对其访问

    2、好处

    • 将变化隔离
    • 便于使用
    • 提高重用性
    • 提高安全性
    class FengZhuang{
        private int age = 15;
        public void setAge(int age) {
            if (age > 0) {
                this.age = age;
            }
        }
        public int getAge() {
            return this.age;
        }
    }

    继承

    java支持单继承,不直接支持多继承。

    因为如果支持多继承,会产生调用的不确定性。(当继承的两个父类含有相同名字的方法时,不确定调用哪个。

    继承可以解决代码复用的问题,当多个类存在相同的属性和方法时,我们可以从这些类中抽取出父类,在父类中定义这些属性和方法,只需要通过extends语句来声明继承父类。
    父类的哪些属性可以被子类继承:

    • public
    • protected
    • 默认修饰符
    • private(只是继承后,相应的变量仍是私有的,不能直接访问)

    1、子父类成员属性的特点package 继承;

    public class Test1 {
        public static void main(String[] args) {
            Zi zi = new Zi();
            zi.num = 3;//zi对象中没有自己写num属性,这个num属性是从父类中继承过来的
            zi.show();
            Zii zii = new Zii();
            zii.show();  //奇怪,zi.num = 3 不是改变了父类中的num的值嘛?zii.show中的num不也应该等于3嘛?可是为什么等于2.可以知道成员继承只是实现了代码的复用,而不是内存的复用
        }
        
    }
    
    class Fu{
        int num1 = 1;
        int num = 2;
    }
    
    class Zi extends Fu{
        int num2 = 4;
        public void show() {
            System.out.println(num + "..." + num);//3...3
    System.out.println(this.num + "..." + super.num);//3...3 this 代表该类对象的引用。 super 代表一个父类空间。 System.out.println(num2 + "..." + num1);//4...1 } } class Zii extends Fu{ public void show() { System.out.println(this.num + "..." + super.num);//2...2 } }

    从上面的例子看成员变量的内存分析图。

     

    2、子父类成员方法的特点

    public class Test2 {
        public static void main(String[] args) {
            Demo1 d = new Demo1();
            d.show();
        }
    }
    
    class Demo{
        String name;
        public void show() {
            System.out.println("fu show run");
        }
        
        public Demo() {
            
        }
        
        public Demo(String name) {//构造方法的重载
            this.name = name;
        }
    }
    
    class Demo1 extends Demo{
        public void show() {//父类方法的重写
            System.out.println("zi show run");
        }
    }

    函数的两个特性

    1、重载(同一个类中)

    • 方法名可以相同
    • 方法的参数类型、个数、顺序至少有一项不同
    • 方法返回值类型可以不同
    • 方法的修饰符可以不同
    • 仅仅只是返回类型或修饰符不一样,不能构成重载

    2、重写(子父类中)

    • 子类的方法的返回类型、参数、方法名、要和父类的完全一致(也就是说修饰符可以不一致,请看第二条),否则就不构成重写
    • 子类方法不能缩小父类方法的访问权限(即修饰符问题)
    • 什么时候使用重写:当对一个类进行子类的扩展时,子类需要保留父类的功能声明。但是要定义子类中该功能特有的内容时,可以使用重写。

     3、子父类构造函数的特点

    public class TestSuper2 {
        public static void main(String[] args) {
            System.out.println("开始创建一个ChildClass对象");
            new ChildClass1();
            
        }
    }
    
    class FatherClass1 {
        int m = 12;
        static {
            System.out.println("hello");
        }
        public FatherClass1() {
            System.out.println(m);
            System.out.println("创建FatherClass");
            show();
        }
        public void show() {
            
            System.out.println("Father show");
        }
    }
    class ChildClass1 extends FatherClass1 {
        int num = 15;
        
        static {
            System.out.println("hello1");
        }
        
        public void show() {
            System.out.println("Child show..." + num);
        }
        
        public ChildClass1() {
            super();
            //super执行完后,才对子类ChildClass1进行成员变量的显示初始化
            System.out.println(num);
            System.out.println("创建ChildClass");
        }
    }

    直接看运行结果,我们再来分析。在分析之前,我们先明确一个概念:构造函数用于对象的初始化,而静态初始化块用于类的初始化

    开始创建一个ChildClass对象
    hello
    hello1
    12
    创建FatherClass
    Child show...0
    15
    创建ChildClass

    分析:

    • 程序首先从main方法入手,先打印出“开始创建一个ChildClass对象”。之后创建一个ChildClass1的实例。
    • 在实例化之前,先进行类加载。先沿着继承树上溯到Object类。先执行Object类的静态初始化块,在向下执行子类的静态初始化块,直到我们实例化类的静态初始化块为止。类的初始化过程只进行一次。(即先进行类加载,类加载过程只进行一次)。这就是为什么会先后打印出hello和hello1。
    • 在堆内存中开辟空间,分配地址。并在对象空间中,对对象中的成员变量进行默认初始化。
    • 调用构造函数,进行特定数据的初始化(即this.name = name等)。这里要注意:在调用构造函数前已经完成成员变量的默认初始化。
    • 进入构造函数时,第一行会先调用父类的构造函数进行父类初始化。(调用父类的构造函数前,也已经完成了父类的默认初始化)。先后打印出:12,创建FatherClass,Child show...0。
    • 父类的super()函数执行完毕后,执行栈返回子类的构造函数,再对子类的成员变量进行显示的初始化。(此时输出15)
    • 最后进行的是对特定数据的初始化。即this.name = name等。

    需要注意的是:成员变量的默认初始化是在调用构造函数之前,而显示初始化是在进入构造函数调用父类的super()方法之后。特定数据的初始化则在最后进行。

    多态

    1、成员属性的特点

    package 多态;
    
    public class chengyuanshuxing {
        public static void main(String[] args) {
            Fu zi = new Zi();
            System.out.println(zi.num);//4
        }
    }
    
    class Fu{
        int num = 4;
    }
    
    class Zi extends Fu{
        int num = 5;
    }

    多态时,成员属性的特点:

    • 编译时,参考父类型上是否有调用的成员属性,有则编译通过,没有则编译失败。
    • 运行时,参考父类型中是否有该成员属性,运行该成员属性。
    • 简单说编译和运行都参考左边

    2、成员函数的特点

    package 多态;
    
    public class chengyuanshuxing {
        public static void main(String[] args) {
            Fu zi = new Zi();
            zi.show();//"zi show"
        }
    }
    
    class Fu{
        void show() {
            System.out.println("fu show");
        }
    }
    
    class Zi extends Fu{
        void show() {
            System.out.println("zi show");
        }
    }

    多态时,成员函数的特点:

    • 编译时,参考父类型上是否有调用的成员方法,有则编译通过,没有则编译失败。
    • 运行时,参考的是对象所属的类中是否有该成员方法,运行该成员方法。
    • 简单说编译看左边,运行看右边

    虽然类型是父类型,但是运行时this指向的是当前new实例的引用。

    3、静态方法的特点

    package 多态;
    
    public class chengyuanshuxing {
        public static void main(String[] args) {
            Fu zi = new Zi();
            zi.show();//"fu show"
        }
    }
    
    class Fu{
        static void show() {
            System.out.println("fu show");
        }
    }
    
    class Zi extends Fu{
        static void show() {
            System.out.println("zi show");
        }
    }

    多态时,静态方法的特点:

    • 编译时,参考父类型上是否有调用的静态变量,有则编译通过,没有则编译失败。
    • 运行时,参考父类型中是否有该静态变量,运行该静态变量。
    • 简单说编译和运行都参考左边

    静态方法是基于类的,而多态是基于对象的,所以调用时,该对象是那个类型的就调用相应类的静态方法。且静态方法不具有多态性

    参考文章

    Java类变量和成员变量初始化过程

    Java中各成员变量初始化流程

  • 相关阅读:
    Implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGB
    iOS谋职之OC面试题
    IOS_视图实现圆角效果的三种方法及比较
    Objective-C 中的方法回掉
    returnValue of Chrome
    获取最新ADT下载地址的方法
    Git 分支使用
    Windows下运行jekyll,编码已不再是问题
    Github Pages另一个选择:GitCafe-Pages
    还没更换RubyGems镜像?
  • 原文地址:https://www.cnblogs.com/yuliangbin/p/9339084.html
Copyright © 2011-2022 走看看