【黑马程序员】Java基础学习技术博客——面向对象

------- android培训java培训、期待与您交流! ----------

方法详解

     方法存在所属性。

       ★  一旦将一个方法定义在一个类里,如果用static修饰了,这个方法属于该类本身,否则属于这个类的实例.
           有static修饰,属于类;没有static修饰,属于对象。
       ★ 方法不能独立执行,必须要有调用者.(如:类.方法、对象.方法)

           方法必须由属主调用。谁的方法,谁调用。
           没有static的方法,属于对象,由对象调用。
             有static的方法,属于类,由类调用。
       ★ 方法不能独立定义,只能定义在类里.
           方法要么属于一个类(有static),要么属于一个对象(无static)

      static在Java中的作用: 它只是标志,有static的修饰的东西,就属于类本身;没有static修饰的,就属于对象。

      调用方法时,总是需要主调(主语调用者),如果方法有static修饰,要用类做主调。
                                              如果方法没有static修饰,要用对象做主调。

      在有些时候,可以省略主调——

          如果在没有static修饰的方法中调用另一个方法,默认可以省略this.前缀。
          如果在没static修饰的方法中调用另一个没static的方法,默认可以省略this.前缀。
          如果在没static修饰的方法中调用另一个有static方法,默认可以省略 类名.前缀。
          如果在有static修饰的方法中调用另一个有static方法,默认可以省略 类名.前缀。
          如果在有static修饰的方法中调用另一个没static方法——这种调用是不允许的。


      ★ 形参个数可变的参数。
 
          如果在形参类型的后面添加...,表明该参数个数可以是0~N个。即调用时,可传入多个参数值。

          个数可变的参数,本质就是数组!
         String ... , 完全相当于 String[]

         调用方法时,定义为形参类型...比定义数组类型的参数更方便。


         形参个数可变的参数的限制: 必须位于形参列表的最后。
                  ——因此一个方法中,最多只能有一个形参个数可变的参数。

     
      ★ Java方法的传参机制。

           Java只支持一种传参模式: 值传递。

           值传递的含义是:当我们传入参数时,实际上并不是把参数本身传入,而是只传入该参数的副本(copy)。

           因此当我们在方法中对参数进行任何修改时,对参数本书并不会有任何影响。


      ★ 递归方法

         所谓递归:就是指,在方法里再次调用自身。

         递归,相当于一个隐式的循环。递归,也要有一个结束点。

         比如有一个数列: f(1) = 2; f(2)=5;
                          f(n) = f(n+2) - 2 * f(n+1);

         计算f(10)的值。

         【注意:】递归一定要有结束点。

         可以考虑对    f(n) = f(n+2) - 2 * f(n+1) 公式进行变换。定义一个新的N, 让N = n + 2.
         公式可改为:   f(N-2) = f(N) - 2 * f(N-1)
                       f(N) = 2 * f(N-1) + f(N-2)
    

     ★ 方法重载

         口诀: 2同1不同。
               同一个类中、方法名相同,形参列表不同(只考虑形参的类型与顺序)。

             修饰符不同不算!返回值类型不同,也不算。

         Java调用方法时,要确定一个方法,需要3个东西:
            1. 调用者
            2. 方法名。
            3. 参数列表。
              

▲  变量详解
                         ↗  类变量(有static修饰),属于类,用于描述类本身的状态
                成员变量
             ↗          ↘  实例变量,属于各个实例,用于描述实例的状态
       变量

                          ↗  方法局部变量: 在方法中声明的变量
             ↘          
                局部变量  →  代码块的局部变量, 在代码块中声明的变量。

                          ↘  形参


       类变量,用描述类的状态;实例变量,用于描述实例的状态。

       如果要访问类变量(获取值, 也包括对它赋值),必须指定类作为主调。
       如果要访问实例变量(获取值, 也包括对它赋值),必须指定的对象作为主调。
      
       Java程序的. ,有点类似于汉语的 "的".

      ★ 成员变量可以不指定初始值.
         如果程序员没有为成员变量指定初始值,系统会为之分配默认的初始值,规则为,
         与动态初始化数组时,数组元素的初始化规则完全相同。

        
         类变量,并不是属于对象,而是属于类本身,当系统初始化类时,就会为类变量分配内存、并指定初始值。

         垃圾语法:【Java允许通过对象来访问类变量、也可调用类方法】

         以后你们编程时,永远不准通过对象来访问类变量、也不准通过对象来调用类方法。应该用类名。

         但以后,如果你在面试、考试...遇到有人通过对象来访问类变量、通过对象来调用类方法,
         首先你先用把对象换成类名——这才是本质。

         成员变量的作用域:

               类变量:从类加载、并初始化开始有效, 直到该类被销毁时无效。
                       如果是官方JVM,JVM不退出,类信息就不会被销毁。
                       尽量少用static修饰的变量。
               实例变量:有多少个对象,就有多少个实例变量。每个对象都会持有自己的实例变量。
                         从对象加载、并初始化开始有效, 直到该对象被销毁时无效。
                         只要一个对象没有引用变量指向它,它就变成垃圾,垃圾回收器将会在接下来时间里回收它。

★ 局部变量
       
        1. 局部变量必须由于程序员显式赋值。
           如果程序员没有赋值,该局部变量不能被使用。
        2. 局部变量的作用域很短, 所有局部变量都保存在各自的方法栈区中。

             形参:方法结束,就失效。
             方法局部变量:从声明它开始有效,方法结束,就失效。
             代码块局部变量:从声明它开始有效,代码块结束,就失效。

     总则:优先使用作用域更小的变量,好处:
           1. 节省内存。
           2. 更符合程序“高内聚、低耦合”的原则。

▲  封装

      面向对象有3大特征: 封装、继承、多态。

      ★ 什么是封装(合理隐藏、合理暴露)
           1. 要类内部的实现细节隐藏起来。
           2. 将一些操作方法暴露出来。

         封装,可以避免直接访问对象的内部细节,从而造成破坏。
               通过合理的暴露,可以简化对象的操作。

      ★  Java的封装,靠的修饰符。

          private  : 类访问权限。
                      如果一个成员(field、方法、内部类、构造器)用private修饰,表明该成员只能在当前类中被访问。
                      【彻底隐藏】
          默认     : 包访问权限。
                      如果一个成员(field、方法、内部类、构造器)不用访问控制符修饰,
                      表明该成员只能在当前类或当前包中被访问。
                      【部分隐藏】
          protected: 子类访问权限
                      如果一个成员(field、方法、内部类、构造器)用protected访问控制符修饰,
                      表明该成员可以在当前类、当前包、该类的子类中被访问。
                      【部分暴露】
          public:    公开访问权限
                      如果一个成员(field、方法、内部类、构造器)用public访问控制符修饰,
                      表明该成员可以在任意地方被访问。
                      【彻底暴露】

     ★  包

         主要用于解决类名冲突的问题。

         世界上无数公司都会定义类,势必造成类名重复。
 
         为了解决类名重复的问题,Java要求在类的前面增加一个“前缀”——这就是所谓的包。
 
         Java建议,包名,用公司的 域名倒写.项目名 —— 包名应该是所有字母小写。

         要一个类加包,要做如下两件事情:
            - 在源代码中使用package定义包。
            - 把生成的class文件放在对应的文件结构下。

         如果一个类位于指定包下,那么该类的完整类名应该 包名+类名, 光写类名是错的。

          以后用该类时,就需要写包名+类名

          为了避免在源代码中总要写包名+类名,就可用import来导入包。

          import有两种格式:
            import java.util.*; *只能代表类,用于表示导入指定包的所有类。
            import 包名.类名 —— 只导入一个类。

     Java源代码默认会 import java.lang.*


▲ 包
      解决命名空间问题。

      要为一个类定义包:
         1. 要在源代码中添加package 包名;
         2. 将生成class文件放在包对应的文件结构下。
            可以在编译Java程序时,增加一个-d 选项,编译器将会为我们自动创建文件结构、并将class文件放入指定的文件结构下。


      一个类有了包之后,我们要注意:
        类名  = [包名 + 类名]

          [包名 + 类名]才是完整的类名。

      为了避免在编写Java程序时,总需要写包名,可用import来导入指定类,或指定包的所有类。

      import  - 可以让不写包名。
          import语句中的*只能代表任意类。
    
      ★ 静态导入

         import static - 可以不写类名。

         import static可用于导入指定类的指定static Field,或static方法。
                      也可用于导入指定类的全部static修饰成员。

         import static语句中的*只能代表指定类的静态成员。
       

       import的作用是在源代码中省略写包名。
       import static的作用是在源代码中省略写类名。

▲ 封装

      1. 把内部实现细节进行隐藏,合理隐藏。
      2. 把操作方法进行暴露, 合理暴露。

      private   类访问权限(只能在当前类中被访问) , 彻底隐藏。
      默认      包访问权限(只能在当前类、当前包中被方法), 部分隐藏。
      proteced  子类访问权限(可以在当前类、当前包、子类中被访问)、部分暴露。
      public    公开访问权限(在任意地方被访问) , 彻底暴露。
 
      javadoc - 生成API文档——就是所写类的使用说明书。
                默认只提取public、protect修饰的类、方法、Field、构造器等成员之前(在成员体内无效)的文档注释。

       为什么只提取public、protect修饰的成员之前的文档注释呢?
         因为所有的使用说明书都只介绍暴露出来的东西。 Java程序中只有用proteced  、public修饰的才算暴露,所以javadoc默认只提取它们之前的文档注释。

       当你查API文档时,如果没有看到public、private、protect等修饰符,API文档中成员是public修饰。


      建议:
          1. 将所有field用private修饰。
             这就是将该field彻底隐藏在该类里面。
          2. 为每个field提供public修饰getter和setter方法,
             允许程序通过getter方法来访问该field的值,并通过setter方法去修改该field的值。
          3. 如果只需要在当前类使用的、为其他方法提供支持的工具方法,也应该使用private修饰。
          4. 如果有些方法,希望被子类重写,该方法应该声明为protected。
     
▲ 构造器

      构造器的作用: 用于初始化对象。
                     必须通过new 构造器来调用它。

     所有类,都有构造器!
       如果我们为类写了构造器,自然就有构造器。
          如果我们没有写构造器, 系统会自动提供一个无参数的构造器。


     ★ 构造器重载
 
        方法重载: 2同1不同

        构造器重载与方法重载几乎是相似的:构造器名必然相同;形参列表不同。

       
        示例: Wolf.java

       this关键词有两个作用:
         1. this引用 —— 如果在构造器中,代表构造器正在初始化的对象。
                          如果在方法中,代表正在调用该方法的对象。
            this引用总是代表该类的实例。

         2. this调用:
             只能用在构造器、而且必须是构造器中第一条代码。
             this调用总是调用当前类中重载的构造器。this调用到底调用哪个构造器,取决于传入的参数值。

            this调用更好! 因此它可以直接复用已有的构造器。
                            1. 代码更简洁。 2. 更有利于以后维护。提高了可维护性。

▲ 继承
     面向对象的3大特征: 封装、继承、多态

     理解继承:

       1. Java的继承,并不是现实生活中的继承。
           Java的继承是一种类与类之间关系,是一种“由一般到特殊”的关系。子类对象一种特殊的父类实例。
            《Thinking In Java》, “is a” 关系。

          父类 - 大类 ;子类 - 小类。

    2. Java的继承,是单继承。 extends后最多只有一个类。

           每个类,只能有一个直接父类。但实际上能有很多的间接的父类。

        示例:Animal 、 Bird 、Sparrow

          如果你没有显式指定extends ,默认是extends Object。
           "所有类都是Object的子类"


        当子类extends父类之后,就可以自动从父类那里“获取”如下东西(这就是为啥叫继承):
             1. field。
             2. 方法。
            

      ★ 重写(覆盖 override)父类的方法

          当子类从父类那里继承得到某个方法,但又不适用子类的行为,此时就要重写父类的方法。
 
          方法重写: 2同2小1大
            2同:方法名相同、形参列表相同。
            2小:返回值类型相同或更小(要么类型相同,要么返回值类型是子类)
                 声明抛出的异常类型相同或更小。
            1大:访问控制权限必须相同或更大。

          如果是方法重写,建议在方法前增加【@Override】修饰。
         

      ★ super
 
          super有两个作用:


            A  super限定:
                   强制指定访问从父类继承得到的field、调用从父类继承得到方法。

                   super.Field
                   super.方法名

                super限定的作用:
                   如果当前类中定义了与父类同名的field、重写了父类的方法
                   ——如果在该类中直接访问该field、调用方法,默认是访问当前类的field、调用当前类的方法。

            B super调用

              super调用是显式调用父类的构造器。 到底调用哪个构造器,取决于传入的参数。
              this调用是当前类中重载的构造器。  到底调用哪个构造器,取决于传入的参数。

                  super调用只能在构造器用,而且必须位于第一行。

              this调用与super调用不能同时出现。

              【规则:】 子类构造器【总】会调用父类的构造器。只调用一次!
                          1. 如果子类构造器中,没有使用super调用,子类构造器会自动调用父类无参数的构造器。
                          2. 如果子类构造器中有使用super调用,根据传入的参数显示调用父类对应的构造器。

              【注意】: 子类构造器总会调用父类的构造器。
                        当父类没有无参数的构造器时,子类的构造器中【必须显式】地用super调用父类有参数的构造器。
                              否则:子类构造器会自动(隐式)调用父类无参数的构造器——必然导致找不到构造器的错误。

       【体会】

              Plant → Apple →  RedFuji

      总结: 无论你创建哪个对象,系统最先调用的总是Object类的无参数构造器。


▲ 多态

       变态:当做同一件事情时,某个个体表现成“变异”的行为特征,就是变态。

       多态的定义:同一个类型的变量,调用同一个的方法(做同一件事情),呈现出多种行为,这就是多态。


       对于一个引用变量来说,可以认为有两个类型:
           1. 编译时类型。声明该变量时所用的类型,就是编译时类型。
               对于编译器来讲,编译器只管变量的编译时类型,与运行时类型无关。
           2. 运行时类型(实际类型)。该变量实际所指向的对象的类型,就是运行时类型。


             
       ★强转
       有一个新的运算符: 强制类型转换。 ()

            限制: 强制类型转换(),只能在两个类型具有继承关系才可转换,否则编译时就会报错。

                   必须运行时类型真正是要强转的类型,才可以强转成功;否则会引发ClassCastException

       ★ instanceof 运算符

          变量 instanceof 类型,
            当该变量所引用的对象,是后面的类、或子类的实例时,就会返回true。否则返回false。

           限制: instanceof,只能在两个类型具有继承关系才可判断,否则编译时就会报错


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值