zoukankan      html  css  js  c++  java
  • Java基础(一)——面向对象

    一、对象

    1、成员变量和局部变量的区别

      两类变量同名时,局部变量具有更高的优先级。
      作用域不同:局部变量的作用域仅限于定义它的方法,作用于函数或者语句中;成员变量的作用域在整个类中。
      初始值不同:Java会给成员变量一个初始值;Java不会局部变量赋予初始值。
      在内存中的位置:成员变量存在堆内存中,因为对象的存在而存在;局部变量存在栈(局部变量表)内存中。

    2、构造函数

      强引用、弱引用,做缓存,内存优化用的。
      特点:函数名与类名相同。不用定义返回值类型。不可以写return语句。
      注意:默认构造函数的特点。多个构造函数是以重载的形式存在的。一般函数不能调用构造函数。

    3、构造代码块

      在类的声明中,可以包含多个构造代码块,当创建类的实例时,会依次执行这些代码块 。
      作用:给对象进行初始化。对象一建立就运行,而且优先于构造函数执行。
      与构造函数的区别:构造代码块是给所有对象进行统一初始化,是对不同对象的共性进行初始化,而构造函数是给对应的对象初始化。
      代码示例:

     1 public class Main {
     2     {
     3         num = 200;
     4     }
     5     public int num = 10;
     6     
     7     public static void main(String[] args) {
     8         Test test = new Test();
     9 
    10         System.out.println(test.num); // 10
    11     }
    12 }
    13 
    14 
    15 public class Main {
    16     public int num = 10;
    17     {
    18         num = 200;
    19     }
    20 
    21     public static void main(String[] args) {
    22         Test test = new Test();
    23 
    24         System.out.println(test.num); // 200
    25     }
    26 }

    4、对this的理解

      this到底代表什么?
      this代表本类的对象。代表它所在函数所属对象的引用(函数和变量是属于哪个对象的。或者说是哪个对象在调用这个函数,这个变量,他就属于哪个对象)。简单说:哪个对象在调用this所在的函数,this就代表哪个对象。
      this的作用:用于区分成员变量和局部变量。用于构造函数之间的调用。
      this的应用:当定义类中函数时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。但凡是本类功能内部用到本类对象时,用this。this语句:用于构造函数之间的相互调用。且只能用this (不能直接访问)。且必须是构造函数中的第一个语句,因为初始化要先执行。

    二、静态static

    1、介绍

      static关键字,只能用于修饰成员(成员变量和成员函数)。被修饰后的成员具有以下特点:
      特征:随着类的加载而加载(重点理解),消失而消失;优先于对象存在(重点理解);被所有对象所共享;可以直接被类名调用。
      存储区:类变量随着类的加载而存在于方法区;实例变量随着对象的建立而存在于堆内存中。
      生命周期:类变量随着类的存在而存在,消失而消失,它的生命周期最长;实例变量生命周期随着对象的消失而消失。
      注意:静态方法只能访问静态成员,无法从静态上下文访问非静态变量;静态方法中不可以写this,super关键字,因为静态优先于对象存在;静态成员属于整个类,当系统第一次使用该类时,就会为其分配内存空间直到该类被卸载才会进行资源回收!

    2、main函数

      主函数是一个特殊的函数,作为程序的入口,格式是固定的,可以被JVM调用。JVM在调用主函数时,传入的是new String[0]。定义如下:

      public:代表该函数访问权限是最大的。
      static:代表主函数随着类的加载就已经存在了。
      void:主函数没有具体的返回值。
      main:不是关键字,但是是一个特殊的单词,可以被JVM识别。
      String[] args:函数的参数,参数类型是一个字符串数组。

    3、静态代码块

      随着类的加载而执行,只执行一次。并优先于主函数。同时静态代码块只能给静态变量赋值,不能初始化普通的成员变量
      执行顺序:
      (无继承)静态代码块-->构造代码块-->构造函数。
      (有继承)先父亲后儿子。

     1 // 无继承关系
     2 public class StaticTest {
     3     static {
     4         System.out.println("StaticTest 静态代码块");
     5     }
     6 
     7     {
     8         System.out.println("StaticTest 构造代码块");
     9     }
    10 
    11     public StaticTest() {
    12         System.out.println("StaticTest 构造器");
    13     }
    14 
    15     public static void main(String[] args) {
    16         System.out.println("-------------A----------");
    17 
    18         new T().method();
    19         new T();
    20 
    21         System.out.println("-------------B----------");
    22 
    23         new StaticTest();
    24     }
    25 }
    26 
    27 class T {
    28     static {
    29         System.out.println("1");
    30     }
    31 
    32     {
    33         System.out.println("2");
    34     }
    35 
    36     public T() {
    37         System.out.println("3");
    38     }
    39 
    40     public void method() {
    41         System.out.println("T-----method");
    42     }
    43 }
    44 
    45 // 结果
    46 StaticTest 静态代码块
    47 -------------A----------
    48 1
    49 2
    50 3
    51 T-----method
    52 2
    53 3
    54 -------------B----------
    55 StaticTest 构造代码块
    56 StaticTest 构造器

      说明:首先,记住几个知识点:

      ①、静态代码块随着类的加载而执行,因为一个类只会被加载一次,所以静态代码块也只执行一次。且优先于main函数。

      ②、先有类,再有对象。构造代码块优先于构造函数(这个下一节还会提到)。

      这样,就不难得出上面的结果:

      ①、因为main方法是StaticTest类的,所以执行main之前,需要装载StaticTest类,那么装载StaticTest,就会执行他的静态代码块。

      ②、new T().method();需要创建 T 的对象,就需要装载 T 类,同理,装载 T 类会执行 T 的静态代码块,后面是 2  3 不难理解。然后调用method()方法。

      ③、new T();由于一个类只会被装载一次。所以后面再是 2  3 。 没有 1 。接着后面的打印也不难理解。

     1 // 有继承关系
     2 public class Son extends Father {
     3     static {
     4         System.out.println("6");
     5     }
     6 
     7     {
     8         System.out.println("7");
     9     }
    10 
    11     public Son() {
    12         // 会默认调用父类的无参构造器 super();
    13         System.out.println("8");
    14     }
    15 
    16     public static void main(String[] args) {
    17         new Son();
    18     }
    19 }
    20 
    21 class Father {
    22     static {
    23         System.out.println("1");
    24     }
    25 
    26     {
    27         System.out.println("2");
    28     }
    29 
    30     public Father() {
    31         System.out.println("3");
    32     }
    33 }
    34 
    35 // 结果
    36 1 6 2 3 7 8

      说明:先父类后子类。再结合上面的知识点,不难理解结果。

    三、对象的初始化过程

    1、成员变量

      默认初始化-->显示初始化,构造代码块初始化-->构造函数初始化(重要)。显示初始化,构造代码块初始化,这两依次执行。

    2、对象(有继承)

      父类静态代码块→子类静态代码块→父类构造代码块→父类构造方法→子类构造代码块→子类构造方法
      (1)初始化父类中的静态成员变量和静态代码块 
      (2)初始化子类中的静态成员变量和静态代码块
      (3)初始化父类的普通成员变量和构造代码块(按次序),再执行父类的构造方法
      (4)初始化子类的普通成员变量和构造代码块(按次序),再执行子类的构造方法
      代码示例:其中Y y = new Y();在类 KK 中的位置不同,输出不同,读者可自己验证。

     1 public class Main {
     2     public static void main(String[] args) {
     3         new KK();
     4     }
     5 }
     6 
     7 class KK {
     8 
     9     {
    10         System.out.println("1");
    11     }
    12 
    13     {
    14         System.out.println("2");
    15     }
    16 
    17     public KK() {
    18         System.out.println("KK");
    19     }
    20 
    21     Y y = new Y();
    22 }
    23 
    24 class Y {
    25     public Y() {
    26         System.out.println("Y");
    27     }
    28 }
    29 
    30 // 结果
    31 1 2 Y KK

      知识点:①、类先于对象。②、父类先于子类。③、对象中,成员变量初始化步骤。默认初始化(int num = 0)-->显示初始化、构造代码块初始化-->构造器初始化。

      特别注意:这里的显示初始化、构造代码块初始化,没有绝对的先后顺序,取决于你源代码中的顺序执行。

    四、封装、继承、多态

    1、封装

      指隐藏对象的属性和实现细节,仅对外提供公共访问方式。私有是封装的一种表现形式。

    2、继承

      Java语言中,类只支持单继承,不支持多继承。因为多继承容易带来安全隐患:当多个父类中定义了相同功能,功能内容不同时,子类对象不确定要运行哪一个。
      继承好处:提高代码的复用性。让类与类之间产生了关系,是多态的前提。
      覆盖:子类覆盖父类方法,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败;父类静态方法也只能用静态来覆盖。
      区别:重载,只看同名函数的参数列表;重写(覆盖),子父类方法要一模一样。

      继承的初始化顺序:
      (1)父类-->子类。
      (2)在对子类对象进行初始化时,父类空参数的构造函数也会执行。
      (3)因为子类中所有的构造函数默认第一行都有一条隐式的语句super()。super()会访问父类中空参数的构造函数,所以默认都会访问父类中空参数的构造函数。
      (4)当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。
      (5)当然子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,子类中至少会有一个构造函数会访问父类中的构造函数。

      为什么子类一定要访问父类中的构造函数?

      父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。
      如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。且放在第一行。

      super的应用:

      子类的构造过程当中必须调用其父类的构造方法。
      如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法;如果显示的调用构造方法,必须在子类的构造方法的第一行。
      如果子类构造方法中既没有显示调用父类的构造方法,而父类又没有无参的构造方法,则编译出错。

    3、多态

      对象的多种形态。
      引用多态:父类的引用可以指向本类的对象;父类的引用可以指向子类的对象。
      方法多态:创建本类对象时,调用的方法为本类方法;创建子类对象时,调用的方法为子类重写的方法或者继承的方法。
      不能通过父类的引用调用子类特有的方法。

      引用类型转换:向上类型转换(隐式/自动类型转换),是小类型到大类型的转换。向下类型转换(强制类型转换),是大类型到小类型的转换。instanceof 运算符,用来解决引用对象的类型,避免类型转换的安全性问题。
      成员变量的特点:无论编译和运行,都参考左边(引用类型变量所属的类)。
      静态成员的特点:无论编译和运行,都参考左边(引用类型变量所属的类)。

    4、final关键字

      final可以修饰类,方法,变量和属性。
      特点:final修饰的类不可以被继承;final修饰的方法不可以被覆盖;final修饰的变量是一个常量,只能被赋值一次,且以后不允许修改;内部类只能访问被final修饰的局部变量。final修饰属性不会进行隐式的初始化,必须显示赋值。或在构造方法中显示初始化,但二者只能选其一。

    作者:Craftsman-L

    本博客所有文章仅用于学习、研究和交流目的,版权归作者所有,欢迎非商业性质转载。

    如果本篇博客给您带来帮助,请作者喝杯咖啡吧!点击下面打赏,您的支持是我最大的动力!

  • 相关阅读:
    Atitti 图像处理 图像混合 图像叠加 blend 原理与实现
    Atitit Gaussian Blur 高斯模糊 的原理and实现and 用途
    Atitit 图像处理 灰度图片 灰度化的原理与实现
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    Atitit 实现java的linq 以及与stream api的比较
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库
    Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结
    Atitit apache 和guava的反射工具
    atitit。企业的价值观 员工第一 vs 客户第一.docx
  • 原文地址:https://www.cnblogs.com/originator/p/13892922.html
Copyright © 2011-2022 走看看