JAVA从入门到精通-面向对象05

来源:互联网 发布:算法第四版mobi百度云 编辑:程序博客网 时间:2024/05/17 23:37

面向对象_01

云智科技学习笔记

面向对象概念

 理解面向对象

l  面向对象是相对面向过程而言

l  面向对象和面向过程都是一种思想

l  面向过程

•    强调的是功能行为

l  面向对象

•    将功能封装进对象,强调具备了功能的对象。

l  面向对象是基于面向过程的。

 

 

 面向对象的特点

l  是一种符合人们思考习惯的思想

l  可以将复杂的事情简单化

l  将程序员从执行者转换成了指挥者

l  完成需求时:

•    先要去找具有所需的功能的对象来用。

•    如果该对象不存在,那么创建一个具有所需功能的对象。

•    这样简化开发并提高复用。

举例:

人开门这个例子的分析过程:(名词提炼法)

{

         门.开( ) { 操作门的具体操作 };

}

 

{

         new门().开( );

}

面向对象开发,设计,特征

l  开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。

l  设计的过程:其实就是在管理和维护对象之间的关系。

l  面向对象的特征:

•    封装(encapsulation)

•    继承(inheritance)

•    多态(polymorphism)

在以后的开发中,其实就是在找对象来用,如果没有对象,我们就创建对象。找对象,建立对象,使用对象,并维护对象之间的关系。

类与对象的关系

l  使用计算机语言就是不断的在描述现实生活中的事物。

l  java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义。

l  对象即是该类事物实实在在存在的个体。

 

类与对象(图例)

l  类与对象的关系如图


l  可以理解为:

1.       类就是图纸

2.       汽车就是堆内存中的对象

l  对于同一类事物可以抽取它们的共性的内容,定义在类中。

l  如生活中的汽车,每一台车都有轮胎数和颜色。

l  那么在通过java描述汽车这类事物时,就可以将这两个共性属性作为类中的属性进行定义。

l  通过该类建立的每一个汽车实体都具有该属性,并可以有对象特有的属性值。

类的定义

l  生活中描述事物无非就是描述事物的属性行为

•    如:人有身高,体重等属性,有说话,打球等行为。

l  Java中用类class来描述事物也是如此

•    属性:对应类中的成员变量。

•    行为:对应类中的成员函数。

l  定义类其实在定义类中的成员(成员变量和成员函数)。

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

1.      成员变量:

•  成员变量定义在类中,在整个类中都可以被访问。

•  成员变量随着对象的建立而建立,存在于对象所在的堆内存中。

•  成员变量默认初始化值。

2.      局部变量:

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

•  局部变量存在于栈内存中。

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

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

 

l  创建对象,使用对象

class Car//对Car这类事物进行描述

{

     String color ="red";

     int num = 4;

     void show()

     {

              System.out.println("color="+color+"..num="+num);

     }

}

class CarDemo

{

     public static voidmain(String[] args)

     {

              Car c = newCar();//建立对象

              c.color ="black";//对对象的属性进行修改

              c.show();//使用对象的功能。

     }

}

对象内存结构

Car c1 = newCar();c1.color="blue";

Car c2 = new Car();


只要是用new操作符定义的实体就在会堆内存中开辟一个新的空间。

并每一个对象中都有一份属于自己的属性。

通过对象.对象成员的方式操作对象中的成员,

对其中一个对象的成员进行了修改。和另一个对象没有关系。

匿名对象

l  匿名对象是对象的简化形式

l  匿名对象两种使用情况

•    当对对象方法仅进行一次调用的时

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

Java语言的强引用,弱引用,长引用,短引用?

                    

封装(Encapsulation)

l  封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

l  好处:

•    将变化隔离。

•    便于使用。

•    提高重用性。

•    提高安全性。

l  封装原则:

•    将不需要对外提供的内容都隐藏起来。

•    把属性都隐藏,提供公共方法对其访问。

private(私有)关键字

private关键字:

•    是一个权限修饰符。

•    用于修饰成员(成员变量和成员函数)

•    被私有化的成员只在本类中有效。

l  常用之一:

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

构造函数

特点:

    1. 函数名与类名相同
    2. 不用定义返回值类型
    3. 没有具体的返回值。

作用:

对象一建立就会调用与之对应的构造函数,给对象进行初始化。

注意:

    1. 默认构造函数的特点。
    2. 多个构造函数是以重载的形式存在的。
    3. 当一个类中没有定义构造函数时,那么系统会对该类使用默认无参的初始化构造函数;但是当在类中显式定义了构造函数后,系统默认的构造函数就不存在了。

如下代码的编译出错:

class Demo

{

         publicString name="aa";

         Demo(Stringname){

                   this.name=name;

         }

}

 

public class Construct1

{

         publicstatic void main(String args[])

         {

                   Democ=new Demo();

                   System.out.println(c.name);

         }

}

错误提示为:

错误: 无法将类 Demo中的构造器 Demo应用到给定类型。说明该类使用的构造方法不能被初始化。即验证了默认的无参构造方法不存在了。

 

可以在一个类中定义多个构造函数,以重载的方式存在。以定义该类的不同初始化参数。

l  构造函数与一般函数的不同:

1.      写法上不同;

2.      运行上不同:

构造函数是在对象建立就运行,给对象初始化;而一般方法是对象调用才执行,给对象添加对象具备的功能。

3.      调用上不同:

一个对象建立,构造函数只执行一次;

而一般方法可以被该对象调用多次。

什么时候定义构造函数呢?

当分析事物时,当已初始化就应该具有某些方法和属性,就可以考虑构造函数。

构造代码块:

l  作用:给对象进行初始化,对象已初始化就运行,优先于构造函数。

l  构造代码块与构造函数的区别:

构造函数是对对象进行分别初始化,而构造代码块是对所有的对象进行初始化。

如下例子:

class Demo

{

         publicstatic void main(String args[])

         {

                   Personp=new Person("yedd");

                   System.out.println(p.getName());

                   Personp1=new Person();

         }

}

 

class Person

{

         privateString name="lisi";

         Person(Stringname){

                   this.name=name;

         }

         //构造代码块

         {

                   System.out.println("我是构造代码块");

         }

 

         Person(){}

 

         publicvoid setName(String name)

         {

                   this.name=name;

         }

         publicString getName()

         {

                   returnthis.name;

         }

 

}

 

当上述代码执行时,每次创建出来一个对象都会运行构造代码块,而只会调用相应的构造函数来初始化。

使用方法:

构建对象时,将对象共性的方法定义在构造代码块中。比如,每个小孩出生后,名字可能有或者没有,但是一定都有哭的动作。所以,是否定义名字可以放在不同构造函数里初始化,而哭的方法统一在构造代码块中执行。

 

this关键字

1.      特点:this代表其所在函数所属对象的引用。简单说,哪个对象在调用this,this就代表这个对象。

2.      换言之:this代表本类对象的引用。这是因为在该方法被调用前不确定哪个对象调用,所有采用this来替代。

什么时候使用this关键字呢?

1.        当在函数内需要用到调用该函数的对象时,就用this.例程。

2.        This的应用:

当定义类中的功能时,当函数内部要调用该函数的对象时,这是用this来表示这个对象。但凡本类功能内部使用到该类时,都用this。

如下代码是对this关键字的应用:

public class Demo

{

         publicstatic void main(String args[])

         {

                   Personp1=new Person();

                   Personp2=new Person(30);

                   booleanb=p1.compare(p2);

                   System.out.println(b);

         }

}

 

class Person

{

         privateint age=30;

         Person(){}

         Person(intage){this.age=age;}

         publicboolean compare(Person p)

         {

                   if(this.age==p.age)

                  {

                            returntrue;

                   }else

                   {

                            returnfalse;

                   }

         }

}

 

this语句在构造函数之间进行调用:

public class Demo2

{

         publicstatic void main(String args[])

         {

                   Personp1=new Person();

                   Personp2=new Person(30);

                   booleanb=p1.compare(p2);

                   System.out.println(b);

         }

}

 

class Person

{

         privateint age;

         privateString name;

         Person(){}

         Person(Stringname){this.name=name;}

         Person(intage){this.age=age;}

         Person(Stringname,int age)

         {

                   /*

                   this.name=name;//这个语句也可以用this关键字来在构造函数之间进行调用

                   //this(name);//相当于调用了Person(Stringname){this.name=name;}

                   //this.age=age;

                   this(age);//但是这个语句是不可以的,在使用this关键字时,必须是函数中的第一条语句

                   //如果像上面这么写会报错:错误: 对this的调用必须是构造器中的第一个语句

                   */

                   //可以修改为这样:

                   //this.name=name;//这个语句也可以用this关键字来在构造函数之间进行调用

                   this(name);//相当于调用了Person(Stringname){this.name=name;}

                   this.age=age;

                  

 

         }

         publicboolean compare(Person p)

         {

                   if(this.age==p.age)

                   {

                            returntrue;

                   }else

                   {

                            returnfalse;

                   }

         }

}

注意事项:

this关键字必须放在构造函数的第一个语句。因为初始化动作要先执行。

 

static(静态)关键字

static关键字:

•    用于修饰成员(成员变量和成员函数)

•    被静态修饰的成员变量称之为类变量,而普通变量称之为实例变量。

被修饰后的成员具备以下特点:

•    随着类的加载而加载

1.      在类初始化之前该静态成员已经存在了,同样会随着类的消失而消失,即它的生命周期与类相同。

•    优先于对象存在

1.      由于在类加载之前就已经存在了,所以可以用类名直接调用。

•    被所有对象所共享

•    可以被对象调用,还可以直接被类名调用

使用注意

•    静态方法只能访问静态成员,但是非静态方法可以访问静态资源也可以访问非静态资源。

•    静态方法中不可以写this,super关键字:因为静态资源优先于对象存在,所以静态方法中不能使用this.

•    主函数是静态的

实例变量与类变量的不同:

1.        存在位置不同:

类变量随着类的加载而加载存在于方法区或者叫共享区中,而实例变量存在随着对象的建立而存在于堆内存中。

2.        生命周期不同:

类变量的生命周期最长,随着类的消失而消失;实例变量生命周期随着对象的消失而消失。

静态修饰的利与弊:

1.        好处:对对象的共享数据进行单独空间的存储,节省空间,没有必要为每个对象开辟内存空间。

2.        坏处:生命周期过长,访问出现局限性。(静态虽好,但是只能访问静态资源。)

主函数是静态的详解:

主函数:

是一个特殊的函数,作为程序的执行入口,供JVM调用。

主函数的调用:

1.        Public:代表该函数访问权限最大的。

2.        Static :代表主函数随着类的加载就已经存在了。

3.        Void:主函数没有返回值。

4.        Main:不是关键字,但是是一个特殊的单词,可以被JVM识别。

5.        (String args[]):函数的参数,参数类型是一个数组,该数组中的元素是字符串,字符串类型的数组。

6.        主函数是固定格式的,供JVM识别调用。

 

深入剖析:

1.        JVM在调用主函数是,传入的是newString[0];

System.out.println(agrs.length);既可以得以验证

2.        在两个启动运行类中可以使用该方式调用,并且可以传递参数:

classDemo

{

         public static void main(String args[])

         {

                   String []arr={"aaa","bbbb","ddd","ddfdfa"};

                   MainTest.main(arr);

         }

}

 

classMainTest

{

         public static void main(String args[])

         {

                   for(inti=0;i<args.length;i++)

                   {

                            System.out.println(args[i]);

                   }

         }

}

什么时候使用静态:

l  要从两个方面来入手:

因为静态修饰的内容要有成员变量和函数。

1.        什么时候定义静态变量(类变量)呢?

当对象中出现共享数据时,该数据被静态锁修饰,对象中的特有数据要定义成非静态存在于堆内存中。

2.        什么时候定义静态函数呢?

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

static修饰符的应用---工具类

1.        工具类的特点:

每个应用程序中都有共性的功能,就可以把这些功能单独抽取出来,独立封装,以便复用。

2.        请参看如下代码:

class ArrayTool

{

     public  void sort(int []arr)

     {

              for(inti=0;i<arr.length-1;i++)

              {

                       for(intj=0;j<arr.length-i-1;j++)

                       {

                                 swap(arr,i,j);

                       }

              }

     }

 

     public static voidswap(int []arr,int a,int b)

     {

              int temp;

              temp=arr[a];

              arr[a]=arr[b];

              arr[b]=temp;

     }

 

     public  void print(int []arr)

     {

              System.out.print("[");

              for(inti=0;i<arr.length;i++)

                       if(i!=arr.length-1)

                       {

                                 System.out.print(arr[i]+",");

                       }else

                       {

                                 System.out.println(arr[i]+"]");                  

                       }

     }

 

     public  int getMax(int []arr)

     {

              int max=arr[0];

              for(inti=1;i<arr.length;i++)

              {

                       if(max<arr[i])

                       {

                                 max=arr[i];

                       }

              }

              return max;

     }

 

     public  int getMin(int arr[])

     {

              int min=arr[0];

              for(inti=1;i<arr.length;i++)

              {

                       if(min>arr[i])

                       {

                                 min=arr[i];

                       }

              }

              return min;

     }

}

publicclass Demo

{

         public static void main(String args[])

         {

                   ArrayTool tool=newArrayTool();

                   int arr[]={1,5,4,2,5,25,55};

                   int b=tool.getMax(arr);

                   System.out.println(b);

         }

}

 

发现这样写是有问题的:

1.        对象是用于封装数据的,可是在我们的工具类中并没有封装对象特有的数据。

2.        操作数组的每个方法都没有用到工具对象的特有数据。

3.        这时需要考虑,让程序更严谨,是不需要对象的,所以可以将工具类的方法定义成静态的。

可以对工具类的方法全部定义成静态的:

class ArrayTool

{

         public static void sort(int []arr)

         {

                   for(inti=0;i<arr.length-1;i++)

                   {

                            for(intj=0;j<arr.length-i-1;j++)

                            {

                                     swap(arr,i,j);

                            }

                   }

         }

 

         public static void swap(int []arr,inta,int b)

         {

                   int temp;

                   temp=arr[a];

                   arr[a]=arr[b];

                   arr[b]=temp;

         }

 

         public static void print(int []arr)

         {

                   System.out.print("[");

                   for(inti=0;i<arr.length;i++)

                            if(i!=arr.length-1)

                            {

                                     System.out.print(arr[i]+",")

                            }else

                            {

                                     System.out.println(arr[i]+"]");                  

                            }

         }

 

         public static void getMax(int []arr)

         {

                   int max=arr[0];

                   for(inti=1;i<arr.length;i++)

                   {

                            if(max<arr[i])

                            {

                                     max=arr[i];

                            }

                   }

                   return max;

         }

 

         public static void getMin(int arr[])

         {

                   int min=arr[0];

                   for(inti=1;i<arr.length;i++)

                   {

                            if(min>arr[i])

                            {

                                     min=arr[i];

                            }

                   }

                   return min;

         }

}

 

public classDemo

{

         public static void main(String args[])

         {

                  

                   int arr[]={1,5,4,2,5,25,55};

                   ArrayTool.getMax(arr);

                   System.out.println(b);

         }

}

 

这样,可以方便于使用,但是该类可以被其他程序建立对象的。但是为了更严谨,可以对构造方法定义成private。

优化后的带按摩如下:

class ArrayTool

{        //构造函数私有化

         private ArrayTool(){}

 

         public static void sort(int []arr)

         {

                   for(inti=0;i<arr.length-1;i++)

                   {

                            for(intj=0;j<arr.length-i-1;j++)

                            {

                                     swap(arr,i,j);

                            }

                   }

         }

 

         public static void swap(int []arr,inta,int b)

         {

                   int temp;

                   temp=arr[a];

                   arr[a]=arr[b];

                   arr[b]=temp;

         }

 

         public static void print(int []arr)

         {

                   System.out.print("[");

                   for(inti=0;i<arr.length;i++)

                            if(i!=arr.length-1)

                            {

                                     System.out.print(arr[i]+",")

                            }else

                            {

                                     System.out.println(arr[i]+"]");                  

                            }

         }

 

         public static void getMax(int []arr)

         {

                   int max=arr[0];

                   for(inti=1;i<arr.length;i++)

                   {

                            if(max<arr[i])

                            {

                                     max=arr[i];

                            }

                   }

                   return max;

         }

 

         public static void getMin(int arr[])

         {

                   int min=arr[0];

                   for(inti=1;i<arr.length;i++)

                   {

                            if(min>arr[i])

                            {

                                     min=arr[i];

                            }

                   }

                   return min;

         }

}

Java文档的制作过程

1.        如果有一个工具类提供给我们使用,那么必须设置正确的classpath路径,可以通过如下命令行命令来设置:

Set classpath=.;你的类路径;这样就设置了一个临时类路径。

2.        如果是我们自己写的一个工具类提供给别人使用,那么必须要提供使用API,制作过程如下:

1.      给该工具类加上相应的注释;

2.      使用javadoc命令对该类进行文档生成。

如:该工具类制作如下:

/**

这是一个可以对数组进行操作的工具类,该类中提供了获取最值,

排序等功能。

@author 叶冬冬

@version V1.1

**/

public classArrayTool

{        //构造函数私有化

         private ArrayTool(){}

         /**

                   对一个整型数组进行排序

                   @param arr 整型的数组

         **/

         public static void sort(int []arr)

         {

                   for(inti=0;i<arr.length-1;i++)

                   {

                            for(intj=0;j<arr.length-i-1;j++)

                            {

                                     swap(arr,i,j);

                            }

                   }

         }

 

         /**

                   对一个整型数组中指定的元素位置进行置换

                   @param arr 整型数组

                   @param a 要交换的位置

                   @param b 要交换的位置

         **/

         public static void swap(int []arr,inta,int b)

         {

                   int temp;

                   temp=arr[a];

                   arr[a]=arr[b];

                   arr[b]=temp;

         }

         /**

                   打印输出数组的元素,打印格式为 [element1,element2,,...]

                   @param arr 整型数组

         **/

         public static void print(int []arr)

         {

                   System.out.print("[");

                   for(inti=0;i<arr.length;i++)

                            if(i!=arr.length-1)

                            {

                                     System.out.print(arr[i]+",");

                            }else

                            {

                                     System.out.println(arr[i]+"]");                  

                            }

         }

 

         /**

                   获取整型数组中的最大值

                   @param arr 整型数组

                   @return max 最大值

         **/

         public static int getMax(int []arr)

         {

                   int max=arr[0];

                   for(inti=1;i<arr.length;i++)

                   {

                            if(max<arr[i])

                            {

                                     max=arr[i];

                            }

                   }

                   return max;

         }

 

         /**

                   获取整型数组中的最小值

                   @param arr 整型数组

                   @return min 最小值

         **/

         public static int getMin(int arr[])

         {

                   int min=arr[0];

                   for(int i=1;i<arr.length;i++)

                   {

                            if(min>arr[i])

                            {

                                     min=arr[i];

                            }

                   }

                   return min;

         }

}

使用如下命令进行文档生成:

Javadoc –d myhelpArrayTool.java –author –version

命令说明:

Javadoc:是jdk中提供的文档制作工具,可以生成java类的API文档

-d:表示生成一个目录,如果没有显式指定绝对路径,则在当前路径下生成

myhelp:当前路径下生成存放java文档的目录

ArrayTool.java:需要生成java文档的原文件

-author:在该类的声明注释中提取作者信息

-version:在该类的声明注释中提取版本信息

 

静态代码块

1.        格式:

static

{

         静态代码块的内容;       

}

 

2.        特点:

随着类的加载而执行,只执行一次,并优先于主函数,用于给类进行初始化。

请看如下代码的打印结果:

class Demo

{

        

         public static voidmain(String args[])

         {

                   System.out.println("b");

                   new Demo();

                   System.out.println("c");

                   new Demo();

                   System.out.println("over");

         }

         static

         {

                   System.out.println("a");

         }

 

}

3.        打印结果如下:

a

b

c

over

4.        说明了:

1.      静态代码块优先于main函数执行;

2.      静态代码块执行一次。

注意:

在上面的例子中:

Demo d=null;//这种情况下,静态代码块是不会被加载的

D=new Demo();//只有类被使用了,才会调用静态代码块

5.        总结:

class Demo

{

     public static voidmain(String args[])

     {

              Demo1 d=newDemo1(6);

 

     }

}

 

class Demo1

{

     int age=4;

     //构造函数

     Demo1()

     {

              System.out.println("构造函数。。。没有age");//上面的初始化时,该构造函数没有被调用

     }

     Demo1(int age)

     {

              this.age=age;

              System.out.println("构造函数。。。age");//该构造函数被调用,优先级最低

     }

     //构造代码块

     {

              System.out.println("构造代码块");//初始化类时被调用,优先级次高

     }

 

     //静态代码块

     static

     {

              System.out.println("静态代码块");//初始化时被调用,优先级最高

              //System.out.println("静态代码块"+this.age);//在静态代码块中不能访问非静态资源

     }

}

 

6.        运行结果如下:

静态代码块

构造代码块

构造函数。。。age

1.        说明了在一个类中,静态代码块的执行优先级最高,构造代码块次之,构造函数最低。

2.        同时在静态代码块或者静态方法中不能访问非静态资源。

对象初始化过程:


l  Person p=new Person(“zhangsan”,23);这个语句都做了什么呢?


1.        因为new 用到了Person.class,所以会先找到Person.class文件并加载到内存中;

2.        执行该类中的static代码块,如果有的话,给Person.class类进行初始化;

3.        在对内存中开辟空间,分配内存地址;

4.        在对内存中建立对象的特有属性,并进行默认初始化;

5.        对对象的特有属性进行显示初始化;

6.        对对象的属性进行构造代码块的初始化;

7.        对对象进行对应的构造函数的初始化;

8.        将内存地址赋值给栈内存中的p变量。

l  对象方法被调用过程


l  完成对类的初始化,此时在方法区中加载了静态方法和各个成员方法;

l  对象的成员方法被调用过程:

1.        当某个成员方法被调用时,将该方法在栈内存中建立函数调用栈,并将函数参数传递进去,其中this也是作为一个参数传递到函数栈中,指向该类初始化对象在堆内存中的引用;

2.        然后通过函数执行操作堆内存中的成员属性;

l  类的静态方法被调用过程:

1.        在方法区中的静态方法是通过类名来直接调用的,由于它优先于对象而存在,所以只能通过类名来调用,同时由于此时没有建立对象引用,所以不能操作对象的特有属性。

 

 

原创粉丝点击