美文网首页
毕向东Java基础教程-面向对象

毕向东Java基础教程-面向对象

作者: Lois_Huang | 来源:发表于2019-12-17 18:57 被阅读0次

    面向对象的概念

    举例:大象装进冰箱。

    1. 面向过程
      步骤:打开冰箱--存储大象--关上冰箱。对于面向过程思想,强调的是过程(动作)。
      代表语言:C语言

    2. 面向对象
      步骤:冰箱打开--冰箱存储--冰箱关闭(只用找到冰箱即可)。对于面向对象思想,强调的是对象(实体)。
      特点:
      1、面向对象是一种常见的思想,符合人们的思考习惯
      2、面向对象的出现,将复杂的问题简单化(放在生活中,即是特定的事交给特定的人做)

    • 面向对象让曾经在过程中的执行者,变成了对象中的指挥者
      特征:封装、继承、多态(如果未体现这三个特征,就不能说运用了面向对象的思想 )
      代表语言:C++,Java,C#

    举例:人开门
    两个对象:人和门(名词体现法),开门的方法应该写在门中(门最清楚打开门这个动作)。

    类与对象的关系

    :用Java语言对现实生活中的事物进行描述,通常只关注属性和行为这两方面。定义类其实就是在定义类中的成员——成员:成员变量<-->属性,成员函数<-->行为。
    对象:该类事物的实例,在Java中通过new关键字来创建的。对象的出现,是为了封装数据(类的每个实例,都有自己特有的数据)。

    成员变量&局部变量

    成员变量和局部变量的区别:

    • 作用范围:成员变量定义在类中,整个类都可访问;局部变量定义在函数、语句、局部代码块中,只在所属的区域有效。
    • 存放位置:成员变量存在于堆内存的对象中;局部变量存在于栈内存的方法中。
    • 生命周期:成员变量随着对象的创建而存在,随着对象的消失而消失;局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
    • 初始化值:成员变量都有默认初始化值;局部变量没有默认初始化值 。

    匿名对象

    Example1:当对象对方法仅调用一次时,可简化成匿名对象

    Car c = new Car();
    c.run();
    //可简写为 
    new Car().run();
    

    Example2:匿名对象可以作为实际参数进行传递

    Car c1 = new Car();
    show(c1);
    //可简写为
    show(new Car()); 
    

    基本数据类型/引用数据类型参数传递

    封装

    概念:隐藏对象的属性和实现细节,仅对外提供公共访问方式。
    好处:将变化隔离;便于使用;提高重用性;提高安全性。
    原则:将不需要对外提供的内容都隐藏起来;把属性都隐藏,提供公共方法对其访问。

    private(私有)关键字

    • 是一个权限修饰符
    • 用于修饰成员(成员变量和成员函数)
    • 被私有化的成员只在本类中有效

    将成员变量私有化,对外提供对应的get/set方法对其进行访问。提高对数据访问的安全性。

    封装与私有的区别

    • 私有是封装,封装不是私有。
    • 私有仅仅是封装的一种体现而已。封装是面向对象的一种特征,隐藏实现的细节,但隐藏细节不代表只有私有能做到,只要能做到对方访问不到就能实现封装。(在Java中,最小的封装体是函数,只要知道函数的功能(需要的未知内容,返回值是什么 ))。

    构造函数

    概念:构建创造对象时调用的函数。
    特点:函数名与类名相同;不用定义返回值类型。
    作用:给对象进行初始化。
    什么时候定义构造函数:在描述事物时,该事物已存在就具备的一些内容,这些内容都定义在构造函数中。

    一般函数与构造函数的区别

    • 构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化。
      一般函数:对象创建后,需要函数功能就调用一次。
    • 构造函数:对象创建时,会调用且只调用一次。
      一般函数:对象创建后,可以被调用多次。
    public static void main(String[] args)
    {
        Person p = new Person();
        p.Person();//错误写法
        p.speak();
        p.speak();
    }
    

    注意:默认构造函数的特点;多个构造函数是以重载的形式存在的。

    默认构造函数
    创建对象必须要通过构造函数初始化。

    • 一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数,class Demo{}在编译成Demo.class文件时会自动创建一个成员 Demo(){}
    • 如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了。

    重载:一个类中可以有多个不同的构造函数,给对象不同的初始化,多个构造函数在类中是以重载的形式来体现的,重载的特点为方法名相同,方法参数(参数个数、参数类型)不一样。
    内存图解(构造函数会进栈):

    Example1

    class Person
    {
        String name;
        int age;
        public Person()
        {
            name = "旺财";
            age = 1;
            speak();        //可调用
        }
        public void speak()
        {
            Person();       //错误写法,如果要调用,需写成new Person();
            System.out.println(name + ":" + age);
        } 
    }
    

    Example2:构造函数中可以写return,但并不常用

    class Person
    {
        String name;
        int age;
        public Person(String n, int a)
        {
            if(a < 0) return;
            name = n;
            age = a;    
        }
    }
    

    this关键字

    概念:代表当前对象。this就是所在函数所属对象的引用。简单说:哪个对象调用了this所在的函数,this就代表哪个对象。

    什么时候使用this关键字
    当在函数内需要用到调用该函数的对象时,就用this。
    当成员变量和局部变量重名,可以用关键字this来区分。
    用于在构造函数中调用其他构造函数。(注意:只能定义在构造函数的第一行,因为初始化动作要先执行)

    内存图解

    Example1-1:当前构造函数调用其他构造函数--正确写法

    public class Person 
    {
        private String name;
        private int age;
        
        Person(String name)
        {
            this.name = name;
        }
        Person(String name,int age)
        {
            /*调用Person(String name){...}的构造函数,注意不能写为this.Person(name),因为构造函数不能通过对象来调用,也不能写为Person(name),因为这个实际上就是this.Person(name)的省略形式*/
            this(name);
            this.age = age;
        }
    }
    

    Example1-2:当前构造函数调用其他构造函数--错误写法

    public class Person 
    {
        private String name;
        private int age;
        
        Person(String name)
        {
            this.name = name;
        }
        Person(String name,int age)
        {
            this.age = age;
            this(name);
        }
    }
    

    编译错误:对this的调用必须是构造函数的第一个语句。

    static关键字

    定义:static是一个修饰符,用于修饰成员(成员变量和成员函数)

    class Person 
    {
        String name;                  //对象所特有的数据,成员变量(实例变量)
        static String country = "CN"; //静态变量(类变量)
    }
    

    被static修饰的成员的特点

    • 随着类的加载而存在
    • 优先于对象存在
    • 被所有对象所共享
    • 可以直接被类名调用(也能被对象调用)

    成员变量和静态变量的区别

    1. 两个变量的生命周期不同
      成员变量随着对象的创建而存在,随着对象的被回收而释放。
      静态变量随着类的加载而存在,随着类的消失而消失。

    2. 调用方式不同
      成员变量只能被对象调用。
      静态变量可以被对象和类名调用。

    3. 数据存储位置不同
      成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据。
      静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。

    使用的注意事项

    • 静态方法在访问本类的成员时,只能访问静态成员(非静态方法即可访问静态成员,又可访问非静态成员)
    • 静态方法中不可以写this,super关键字
    • 主函数是静态的

    Example1:在静态方法中可通过对象访问非静态方法

    class StaticDemo
    {
        int num = 4;
        static int data = 10;
        public static void main(String[] args)
        {
            new StaticDemo().show();
            //或 StaticDemo sd = new StaticDemo(); sd.show();
        }
        public void show()
        {
            System.out.println(num); //实际上是this.num
            System.out.println(data);//实际上是StaticDemo.data
        }
    }
    

    static的应用——主函数的特殊之处

    public static void main(String[] args)

    格式固定;被JVM所识别和调用。

    • public:权限必须最大
    • static:不需要对象,直接用主函数所属类名调用即可
    • void:主函数没有具体的返回值( 不然..难道返回给虚拟机?)
    • main:函数名,不是关键字,只是一个jvm识别的固定的名字
    • String[] args:主函数的参数列表,字符串类型数组

    默认情况下传入的值为一个空数组,若要传值,可以通过:

    javac 类名
    java 类名 XX XX ...(字符串参数)
    

    注意:

    class MainDemo
    {
        public static void main(String[] args)
        {
            ...
        }
        public static void main(int x)        //函数的重载而已,这样写不会报错
        {
            ...
        }
    }
    

    内存图解

    • 执行java StaticDemo2后,会开辟空间(栈、堆、方法区(分为非静态区和静态区(存储静态成员))),栈是运行区,方法区是代码置放区。
    • 非静态区和静态区中的方法是所有该类的对象都具有的功能,这些对象唯一的区别是封装的数据不一样。
    • 当执行main方法的第一行时,加载Person类,在classpath路径下找是否有Person.class文件,若没有设置classpath,则在当前目录下找,找到后会把Person.class文件加载进内存。

    静态什么时候使用?

    1. 静态变量
      当对象所具备的成员变量的值都是相同的,那么这个成员就需要被静态修饰;如果是不同的,那就是对象的特有数据,必须存储在对象中,是非静态的。

    2. 静态函数
      函数是否用静态修饰,只参考一点——该函数功能是否需要访问到对象的特有数据(即非静态的成员变量),如果需要,该功能就是非静态的;如果不需要,该功能就是静态的,当然也可以将其定义为非静态,但是非静态需要被对象调用,而仅创建对象调用非静态的没有访问特有数据的方法,该对象的创建没有意义,会造成堆空间的浪费。

      class Demo
      {
          int age;
          static int num = 9;
          Demo(int age)
          {
              this.age = age;
          }
          public static void speak()
          {
              System.out.println("hahaha");
          }
      }
      
      class StaticDemo
      {
          public static void main(String[] args)
          {
              //Demo d = new Demo(30);
              //d.speak();
              Demo.speak();
          }
      }
      

    静态代码块

    特点:随着类的加载而执行,而且只执行一次。
    作用:用于给类进行初始化。(构造函数是给对象初始化的,注意有的类可能不需要对象(如,所有的函数都是静态的))

    class StaticCode
    {
        static int num; //在此处也可以赋值,即static int num = 10,但在此处只能进行一次赋值动作,而在静态代码块里还能对其进行更多的处理
        static
        {
            num = 10;
            num *= 3;
            System.out.println("hahaha");
        }
        static void show()
        {
            System.out.println(num);
        }
    }
    
    class StaticCodeDemo
    {
        public static void main(String[] args)
        {
            //new StaticCode().show();
            //new StaticCode().show();
            StaticCode.show();
        }
    }
    

    一般会用静态代码块对类进行初始化的,那么在这个类中,全是静态成员。

    构造代码块

    类中的独立代码块。
    构造代码块:可以给所有对象进行初始化,具有通用性
    构造函数:给对应的对象(调用该构造函数的对象)进行针对性的初始化。
    构造代码块比构造函数先执行。

    class Person
    {
        private String name;
        {
            cry();
        }
        Person()
        {
            name = "baby";
    //      cry();
        }
        Person(String name)
        {
            this.name = name;
    //      cry();
        }
        public void cry()
        {
            System.out.println("哇哇");
        }
        public void speak()
        {
            System.out.println("name:"+name);
        }
        static void show()
        {
            System.out.println("show run");
        }
    }
    
    class StaticCodeDemo
    {
        public static void main(String[] arg)
        {
            Person p1 = new Person();
            p1.speak();
            Person p2 = new Person();
            p2.speak();
            new Person();
            //以上会输出三遍“哇哇”
            Person.show(); //不会输出“哇哇”,即不会执行构造代码块中的内容
        }
    }
    

    不允许其他类创建某类的对象

    class ArrayTool
    {
        private ArrayTool(){}//该类中的方法都是静态的,所以该类是不需要创建对象的;为了保证不让其它类创建该类对象,可以将构造函数私有化
        
        public static int getMax(int[] arr)
        {
            ...
        }
        
        public static void selectSort(int[] arr)
        {
            ...
        }
    }
    

    相关文章

      网友评论

          本文标题:毕向东Java基础教程-面向对象

          本文链接:https://www.haomeiwen.com/subject/bxdenctx.html