黑马程序员——Java面向对象(一)之匿名对象、代码块、static关键字等

时间:2021-07-14 00:41:48

-----------android培训java培训、java学习型技术博客、期待与您交流!------------ 

 面向对象是Java学习中非常重要的部分,这是Java与其他编程语言设计思想的不同,因此必须要理解与掌握。

一、什么是面向对象?

 面向对象是一种思想,是基于面向过程而言的,面向过程强调的是功能行为,而面向对象将功能封装进对象,强调的是具备了功能的对象。也就是说,面向对象就是把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象。

 示例:把大象装进冰箱

 面向过程为:打开冰箱——>把大象装进冰箱——>关闭冰箱。

 面向对象为:冰箱打开——>冰箱存储——>冰箱关闭。

   从上面示例中可以看出,面向过程像是自己亲自在操作,而面向对象像是指挥别人操作。面向过程强调了自己去打开冰箱、把大象装进冰箱并关闭冰箱,而面向对象则将这些动作封装成一个对象,即冰箱,再指挥冰箱去完成打开、存储、关闭动作。面向对象将自己从执行者变成了指挥者,把复杂的事情简单化,这是面向对象中的一个很重要的特点。


二、面向对象的特点

 1.比较符合人的思考方式。

 2.将自己从执行者便成了指挥者,从而把复杂的事情简单化。

三、对象与类

 1.什么是类?

  类就是对现实事物的描述,在Java中类是具体事物的抽象

 2.类的特点

 1)类中的大多数数据,只能用本类的方法进行处理

 2)class用来描述对象的属性和行为,其中属性是指对应类中的成员变量,行为是指对应类中的成员方法。定义类其实就是在定义类中的成员(成员变量和成员函数)。

 3.类与对象的关系?

  类是对同类对象抽象出其共性而形成,对象是该类实实在在存在的个体。在Java中,类就是用class定义的类,而对象就是用new建立在堆内存中的实体。现在通过一个简单的示例来进行理解:

黑马程序员——Java面向对象(一)之匿名对象、代码块、static关键字等

  在这幅图中,类就表示图纸,而汽车就是对象。

 4.匿名对象

 1)定义:匿名对象是指没有建立对象的引用的对象,它是对象的简化形式。例如:new car ()。

 2)匿名对象的两种使用情况:

  a)如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。

  b)将匿名对象作为实参传递给一个方法调用。

  注:如果对一个对象进行多个成员调用,必须给这个对象起个名字。

 5.成员变量与局部变量

 1)成员变量:

         定义:直接定义在类中的变量或属性,就称为成员变量。

         种类:分为类变量和实例变量。

         如果该成员变量有 static 关键字修饰,则该成员变量称为 静态变量 或 类变量。

           如果该成员变量没有 static 关键字修饰,则该成员变量被称为 非静态变量 或 实例变量

         类变量(或静态变量)的特点:

             a)定义在类中,在整个类中都可以被访问。

             b)类变量随着类的加载而存在于方法区中。

             c)有默认初始化值。

             d)类变量生命周期最长,随着类的消失而消失。

         注:类变量可以直接用类名调用,且只能被初始化一次

         实例变量(或非静态变量)的特点:

             a)定义在类中,在整个类中都可以被访问。

             b)实例变量随着对象的建立而存在于堆内存中。

             c)实例变量生命周期随着对象的消失而消失。

             d)有默认初始化值。

    2)局部变量:

         定义:指在形参、方法内及代码块中定义的变量。

         特点:

            a)局部变量只定义在局部范围内,如:函数内,语句内等。

            b)局部变量存在于栈内存中。

            c)作用的范围结束,变量空间会自动释放。

            d)局部变量没有默认初始化值。


四、类的内容

  1.构造函数

  1)定义:与类名称具有一样名称的成员函数。

  2)格式:

     class 类名

    {

       类名 ()

      {

       super();//默认构造函数里有一句隐式的super语句

      }

    }

 注:该格式为默认构造函数形式,也可自定义构造函数或者重载构造函数。

 3)特点:

   a) 函数名与类名相同。

   b) 如果类中没有定义构造函数,则系统会默认一个空的构造函数。这个默认的构造函数的权限和所属类一致,如果类被public修饰,则默认构函数也带public修饰,反之一样。

   c) 不用定义返回值类型,不可以写return语句。

   d)可以通过重载形式自定义构造函数,这时系统默认的空的构造函数不存在。

   e)构造函数内的第一行如果没有super语句,则系统默认会定义一个super()语句,用来指向父类的构造函数,以便让父类先进行初始化。

 4)作用:给对象进行初始化。  5)继承特性:

   a)子类只继承父类的默认(缺省)构造函数,即无形参构造函数。如果父类没有默认构造函数,那子类不能从父类继承默认构造函数。

   b)子类从父类处继承来的父类默认构造函数,不能成为子类的默认构造函数。

   c)在创建对象时,先调用父类默认构造函数对对象进行初始化,然后调用子类自身自己定义的构造函数。

   d)如果子类想调用父类的非默认构造函数,则必须使用super来实现。

   e)子类必须调用父类的构造函数。系统会自动调用父类的默认构造函数,如果父类没有默认构造函数时,子类构造函数必须通过super调用父类的构造函数。

 6)问题思考:

   a)什么时候定义构造函数?

    当分析事物时,该事物存在时就需具备一些特性或者行为,那么将这些内容定义在构造函数中。

   b)构造函数和一般函数有什么区别?

             —写法上不同:构造函数只有函数名且同类名一致,而一般函数有返回值类型且不能与类名一致。

             —运行上不同:构造函数式在对象一建立就运行,给对象初始化。而一般方法是对象调用才执行,给是对象添加对象具备的功能。一个对象建立,构造函数只运行一次。而一般方法可以被该对象调用多次。

 2.构造代码块

 1)定义:在Java中,使用”{}”括起来的代码称为代码块,而直接定义在类中的代码且无任何声明,就称为构造代码块。

 2)格式:

                    class  类名

                  {

                        {

                             构造代码块语句;

                        }

                  }

 3)特点:

         a)构造块会重复的调用多次。

         b)构造块优先于构造方法。 4)作用:给对象进行初始化。 5)问题思考:         a)构造代码块与构造函数有什么区别?              构造代码块是给所有对象进行初始化,而构造函数是给对应的对象初始化。         b)构造代码块里可以定义那些语句或元素?
 3.静态代码块 1)定义:直接定义在类中,且使用Static声明的代码块,叫做静态块。 2)格式:                   class  类名                {                       static                     {                         静态代码块语句;                      }                 } 3)特点:随着类的加载而执行,只有用到类中的内容才会被加载。只执行一次,并优先于主函数。用于给类进行初始化。         注:特殊情况,如 Person(类)per = null,编译可通过,但没有加载类。 4)作用:用于给类进行初始化。
 4.主函数——main 1)概念:是一个特殊的函数,作为程序的入口,可以被Jvm调用。 2)格式:     public static void main(String [ ]  args)    {      主函数的语句;      } 3)主函数各关键字解释:  public:代表这该函数访问权限是最大的。  static:代表主函数随着类的加载 就已经存在了。  void:主函数没有具体的返回值。  main:不是关键字,但是是一个特殊的单词,可以被Jvm识别。  (String[] arr):函数的参数,参数类型是一个数组,该数组中的元素是字符串。字符串类型的数组。  注:主函数是固定格式的,用于被Jvm识别。 4)问题思考:  a)Jvm在调用主函数的时候,给主函数传入了什么?   Jvm在调用主函数时,给主函数传入了 new String[0].  b)可不可以自定义给主函数传值?如果可以,如何传?   可以自定义给主函数传值,但必须在执行java命令的时候进行传值,示例:java  类名  元素1  元素2  .....   注:元素1、元素2等都为自定义传入的值,必须为字符串类型,因为主函数只接受字符串类型。
 4.关键字——static 1)什么是static?         static是一个修饰符,用于修饰成员,即成员变量和成员函数。当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直          接被类名调用。格式为:类名.静态成员。 2)特点:       

          a)随着类的加载而加载,随着类的消失而消失 ,生命周期最长。                

          b)优先于对象存在,即静态先存在,对象后存在。      

          d)可以直接被类名所调用。

          e)静态方法只能访问静态成员,即静态方法里不能出现非静态成员变量和非静态成员方法。

 3)利弊:  

         利处:对对象共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份,可以直接被类名调用。

         弊端:生命周期过长,只能访问静态,因为静态优先于对象建立。

 4)问题思考

         a)类名调用和new对象有什么区别?

              类名调用只能调用类中的静态成员变量和静态方法,并且是非私有的,类名调用只进行类初始化,即只加载类*享数据,也就是被static所修饰的成员。

              new对象即完成了类*享数据的加载,也完成了对象特有数据的加载或者初始化。

         b)什么时候定义静态变量或类变量?

              当对象中出现共享数据时,该数据被静态所修饰,则定义成静态。

         c)什么时候定义静态函数?

             当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。

         d)为什么静态方法中不可以定义this,super关键字?

             因为静态优先于对象存在,所以静态方法中不可以出现this、super关键字。

  5)静态应用

  工具类帮助文档应用示例:

/*
静态的应用:工具类
每一个应用程序中都有共性的功能,可以将这些功能进行抽取
,独立封装,以便复用。

虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作。
发现问题:
1.对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。
2.操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。

这时就考虑,让程序更严谨,是不需要对象的。
可以将ArrayTool中的方法都定义成静态的,直接通过类名调用即可。

当方法都静态后,可以方便与使用,但是该类还是可以被 其它程序
建立对象,为了更为严谨,强制让该类建立对象,可以通过让构造
函数私有化。

制作程序的说明书,java的说明书通过文档注释完成。
*/


/**
这是一个可以对数组进行操作的工具类,该类中提供了获取最值、排序
等功能。
@author 李四
@version V1.1

*/
public class ArrayTool
{
private ArrayTool(){};
/**
获取一个整形数组中的最大值。
@param arr 接受一个int类型的数组。
@return 会返回一个该数组中的最大值。
*/
public static int getMax(int[] arr)
{
int max=0;
for (int x=1;x<arr.length ;x++ )
{
if(arr[x]>arr[max])
max=x;
}
return arr[max];
}

/**
获取一个整形数组中的小值。
@param arr 接受一个int类型的数组。
@return 会返回一个该数组中的最小值。
*/
public static int getMin(int[] arr)
{
int min=0;
for (int x=1;x<arr.length ;x++ )
{
if(arr[x]<arr[min])
min=x;
}
return arr[min];
}

/**
给int数组进行选择排序。
@param arr 接受一个int类型的数组。
*/
public static void selectSort(int[] arr)
{
for (int x=0;x<arr.length ;x++ )
{
for (int y=x+1;y<arr.length ;y++ )
{
if(arr[x]<arr[y])
{
swap(arr,x,y);
}
}
}
}

/**
给int数组进行冒泡排序。
@param arr 接受一个int类型的数组。
*/
public static void bubbleSort(int[] arr)
{
for (int x=0;x<arr.length-1 ;x++ )
{
for (int y=0;y<arr.length-x-1 ;y++ )
{
if(arr[y]<arr[y+1])
swap(arr,y,y+1);
}
}
}

/**
给int数组中的元素进行位置置换。
@param arr 接受一个int类型的数组。
@param a 要置换的位置。
@param b 要置换的位置。
*/
private static void swap(int[] arr,int a,int b)
{
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}

/**
用于打印数组中的元素,打印形式是:[element1,element2, ...]。
@param arr 接受一个int类型的数组。
*/
public static void printArray(int [] arr)
{
System.out.print("[");
for (int x=0;x<arrr.length ;x++ )
{
if(x!=arr.length-1)
System.out.println(arr[x]+",");
else
System.out.println(arr[x]+"]");
}
}


}

 在dos命令行中输入:javadoc -d 存放的目录 -author -version ArrayTool.java

 Java中的javadoc工具就会自动完成工具类说明文档的制作,也称API的制作。

 如图所示:

黑马程序员——Java面向对象(一)之匿名对象、代码块、static关键字等

 下面就是工具类的API文档:

黑马程序员——Java面向对象(一)之匿名对象、代码块、static关键字等

 

 5.关键字——this

 1)如何理解this关键字?

  this关键字代表本类对象,那个对象调用this所在函数,this就代表哪个对象。

 2)this语句的特点:

  a)用于构造函数之间进行互相调用。如:this(name)。

  b)this语句只能定义在构造函数的第一行,因为初始化要先执行。

 3)this关键字的应用:

  a)当成员变量和局部变量重名时,在方法中使用this时,表示的是该方法所在类中的成员变量(this是当前对象自己)。

  b)把自己当作参数传递时,也可以用this.(this作当前参数进行传递)。

  c)有时候,我们会用到一些内部类和匿名类,如事件处理。当在匿名类中用this时,这个this则指的是匿名类或内部类本身。这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。

  d) 在构造函数中,通过this可以调用同一类中别的构造函数。


 6.关键字——final

 1)什么是final关键字?

  final(最终)是一个修饰符,可以修饰类,函数,变量。

 2)特点:

  a)被final修饰的类不可以被继承,被final修饰的方法不可以被覆盖。

  b)被final修饰的变量是一个常量,并且只能赋值一次,final即可以修饰成员变量,也可以修饰局部变量。

  c)final用于修饰一些固定不变的数据,增强阅读性。被fanal修饰常量,常量名单词全部大写,如果由多个单词组成,则单词之间用_连接。如果在final前还有static和public修饰,则该常量称为全局常量。

 7.对象的初始化过程

 1)把类名.class文件加载到内存中。

 2)执行该类中的static代码块,如果有得话,给该类进行初始化。

 3)在堆内存中开辟空间,分配内存地址。给对象。

 4)在堆内存中建立对象的特有属性。并进行默认初始化。

 5)对属性进行显示初始化。

 6)对对象进行构造代码块初始化。

 7)对对象进行对应构造函数初始化。

 8)将内存地址赋给栈内存中的对象名变量。