黑马程序员 Java自学总结六 面向对象三个特征之封装

来源:互联网 发布:淘宝宝贝新品标签 编辑:程序博客网 时间:2024/04/27 22:51

------ ASP.Net+Android+IO开发.Net培训期待与您交流! ------

总结内容来源于黑马毕老师的java基础教学视频


面向对象思想:面向对象是相对于面向过程而言,面向对象和面向过程都是一种思想,面向过程强调的是功能,而面向对象强调的是将功能封装进对象,强调具备功能的对象.面向对象是基于面向过程的.

例如我想和妈妈说话,我只要找到能帮助我实现该功能的手机,打给我妈妈的就可以了,至于电话是怎么操作的我不知道,我达到了跟妈妈说话的目的,这就是面向对象.在这里手机就是对象,打电话就是手机对象的其中一个功能,手机把打电话功能封装起来了.

从功能封装的角度讲,面向对象和面向过程一样,也是函数,但是面向对象可以将多个联系紧密的函数封装在一起,形成类,当你需要某个功能,只需要调用这个类建立一个对象,拿对象来调用这个功能就行了。

面向对象的开发,就是找对象使用,如果没有对象,就建立一个对象,而程序员要做的就是,找对象,使用对象,建立对象,维护对象之间的关系。

类和对象的关系.

      类就是:对现实生活中事物的描述.

      对象:就是这类事物,实实在在存在的个体.

      描述事物其实就是在描述事物的属性和行为.

      属性对应类中的变量,行为对应类中的函数(方法).

成员变量和局部变量.

作用范围:

       成员变量作用于整个类中.

       局部变量作用于函数中,或者语句中.

在内存中的位置:

       成员变量:在堆内存中,因为对象的存在,才在内存中存在

       局部变量:在栈内存中

匿名对象:顾名思义,就是没有名字的对象,是对象的一种简写形式。

匿名对象特点:

1.可以调用属性,但没有意义;

2.调用方法有意义,但只能调用一次,若对一个对象进行多次成员调用必须给该对象建立引用;

3.可以作为参数传递给函数。

匿名对象练习

[java] view plaincopy
  1. class  Car  
  2. {  
  3.      //描述颜色  
  4.      String color = "红色";  
  5.     //描述轮胎数  
  6.      int num = 4;  
  7.      //运行行为  
  8.      void run()  
  9.      {  
  10.           System.out.println(color+".."+num);  
  11.      }  
  12. }  
  13. class CarDemo  
  14. {  
  15.      public static void main(String[] args)  
  16.      {  
  17.             //匿名对象写法,下面每个语句都是一个单独的匿名对象,互不干扰  
  18.             new.Car().num = 5;//创建一个匿名对象,num=5  
  19.             new Car().color = "blue";//创建一个匿名对象,color="blue"  
  20.             new Car().run();//创建一个匿名对象调用该对象方法  
  21.        
  22.             //匿名对象的使用方式一:当对对象的方法只调用一次时,可以用匿名对象来完成,比较简化.  
  23.             //如果对一个对象进行多个成员调用,必须给这个对象起个名字  
  24.             //匿名对象使用方法二:可以将匿名对象作为实际参数进行传递.  
  25.            Car q = new Car();  
  26.            show(q);  
  27.            //可以写成下面的匿名对象  
  28.            show(new Car());  
  29.      }  
  30.      //需求"汽车修配厂.对汽车进行改装,3个轮子,黑色.  
  31.      public static void show(Car c)  
  32.      {  
  33.           c.num = 3;  
  34.           c.color = "black";  
  35.           c.run();  
  36.           //上面语句在内存中的形式见下图  
  37.      }       
  38. }  

面向对象三个特征:封装,继承,多态.

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

好处:将变化隔离,便于使用,提高重用性,提高安全性.

封装原则:

将不需要对外提供的内容隐藏起来.

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


private:私有,权限修饰符:用于修饰类中的成员(成员变量,成员方法)

私有只在本类中有效.

age私有化以后,类以外即使建立了对象以后,也不能直接访问.

但是人应该有年龄,那么就需要在person类中提供对应的访问age的方式.

注意:私有仅仅是封装的一种表现形式.最小权限.

之所以对外提供访问方式,就是因为可以再访问方式中加入逻辑判断语句.

对访问数据进行操作,提高代码健壮性.

封装练习:
[java] view plaincopy
  1. class Person  
  2. {  
  3.      private int age;  
  4.      public void setAge(int a)  
  5.      {  
  6.           if (a>0 && a<130)  
  7.           {  
  8.                age = a;  
  9.                speak();  
  10.           }  
  11.           else  
  12.           {  
  13.                System.out.println("非法年龄");  
  14.           }  
  15.      }  
  16.      public int getAge()  
  17.      {  
  18.           return age;  
  19.      }  
  20.      void speak()  
  21.      {  
  22.           System.out.println("age="+age);  
  23.      }  
  24. }  
  25. class PersonDemo  
  26. {  
  27.      public static void main(String[] args)  
  28.      {  
  29.           Person p =new Person();  
  30.           p.setAge(40);  
  31.           //p.speak();  
  32.      }  
  33. }  
构造函数

特点:函数于类名相同,不用定义返回值类型,不可以写return语句

作用:给对象进行初始化.

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


对象一建立就会调用与之相对应的构造函数.

构造函数的作用:可以给对象进行初始化.

当一个类中没有定义构造函数时,那么系统会默认

构造函数和一般函数在写法上有不同

在运行上也有不同,构造函数在对象一建立就运行,给对象初始化.

而一般方法是对象调用才执行,是给对象添加对象具备的功能.

一个对象建立,构造函数只运行一次.

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

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

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

例子:

[java] view plaincopy
  1. class Person  
  2. {  
  3.      private String name;  
  4.      private int age;  
  5.      //构造代码块,给对象进行初始化,对象一建立就运行,优先于构造函数执行.  
  6.      //和构造函数区别:构造代码块给所有对象进行初始化.  
  7.      //构造函数给对应的对象初始化.  
  8.      {  
  9.            System.out.println("构造代码块");  
  10.      }  
  11.      Person()  
  12.      {  
  13.           System.out.println("A:name="+name+",,age="+age);  
  14.           cry();  
  15.      }  
  16.      Person(String n)  
  17.      {  
  18.           name = n;  
  19.           System.out.println("B:name="+name+",,age="+age);  
  20.           cry();  
  21.      }  
  22.      Person(String n,int a)  
  23.      {  
  24.           name=n;  
  25.           age=a;  
  26.           System.out.println("c:name="+name+",,age="+age);  
  27.           cry();  
  28.      }  
  29.      void cry()  
  30.      {  
  31.           System.out.println("cry........");  
  32.      }  
  33. }  
  34.   
  35. class PersonDemo1  
  36. {  
  37.      public static void main(String[] args)  
  38.      {  
  39.           Person p = new Person();  
  40.           Person p1 = new Person("lisi");  
  41.           Person p2 = new Person("wangwu",33);  
  42.      }  
  43. }  
this:代表它所在函数所属对象的引用.

简单说,那个对象在调用this所在的函数,this就代表那个对象.

this的应用:当定义类中功能时,该函数内部要调用到调用该函数的对象时,

this表示这个对象.

简单来说就是本类功能内部使用了本类对象,都用this表示.

例子:

[java] view plaincopy
  1. class Person  
  2. {  
  3.      private String name;  
  4.      private int age;  
  5.      Person(String name)  
  6.      {  
  7.           this.name = name;  
  8.      }  
  9.      Person(String name,int age)  
  10.      {  
  11.           this.name=name;  
  12.           this.age=age;  
  13.      }  
  14.      void speak()  
  15.      {  
  16.           System.out.println("name="+name+"  age="+age);  
  17.      }  
  18.      //需求:给人定义一个用于比较年龄是否相同的功能,也就是是否是同龄人  
  19.     public boolean compare(Person p)  
  20.      {  
  21.           return this.age == p.age;  
  22.      }  
  23. }  
  24.   
  25. class PersonDemo2  
  26. {  
  27.      public static void main(String[] args)  
  28.      {  
  29.           Person p1 = new Person("lisi",30);  
  30.           Person p2= new Person("zhangsan",40);  
  31.           boolean b = p2.compare(p1);  
  32.           System.out.println(b);  
  33.      }  
  34. }  

this关键字在构造函数间的调用
[java] view plaincopy
  1. /* 
  2. this语句:用于构造函数之间的互相调用. 
  3. this语句只能定义在构造函数的第一行,因为初始化要先执行. 
  4. */  
  5. class Person  
  6. {  
  7.      private String name;  
  8.      private int age;  
  9.      Person()  
  10.      {  
  11.   
  12.      }  
  13.      Person(String name)  
  14.      {  
  15.           this();//是在调用上面的Person()构造函数  
  16.           this.name = name;  
  17.      }  
  18.      Person(String name,int age)  
  19.      {  
  20.           this(name);//是在调用上面的Person(String name)构造函数  
  21.           this.age=age;  
  22.      }  
  23.      void speak()  
  24.      {  
  25.           System.out.println("name="+name+"  age="+age);  
  26.      }      
  27. }  
  28.   
  29. class PersonDemo3  
  30. {  
  31.      public static void main(String[] args)  
  32.      {  
  33.           Person p1 = new Person("lisi",30);  
  34.           p1.speak();  
  35.      }  
  36. }  
静态:static

用法:是一个修饰符用于修饰成员(成员变量、成员函数)

当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用,

写法是:类名.静态成员

static特点:

1,随着类的加载而加载.

  也就是说:静态会随着类的消失而消失,说明它的生命周期最长,不建议定义过多的静态变量

2,优先于对象存在.

  明确一点:静态是先存在,对象是后存在.

3,被所有对象共享.

4,可以直接被类名调用.

实例变量和类变量的区别:

1,存放位置

      类变量随着类的加载而而存在方法区中.

       实例变量随着对象建立而存在于堆内存中.

2,生命周期:

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

       实例变量随着对象的消失而消失.

静态的使用注意事项:

1,静态方法只能访问静态成员(成员方法和成员变量)

  非静态方法既可以访问静态也可以访问非静态

2,静态方法中不可以定义this,super关键字.

  因为静态优先于对象存在.所以静态方法中不可以出现this.

静态的优缺点

:对对象共享的数据进行单独空间存储,节省空间,可以被类直接调用.

:生命周期过长,访问出现局限性.(静态虽好,只能访问静态)

例子:
[java] view plaincopy
  1. class Person  
  2. {  
  3.      private String name;//成员变量,实例变量  
  4.      //都是中国人,国家是一样的,所以用static,被对象共享  
  5.     static String country = "china";//静态的成员变量,类变量  
  6.      void setName(String name)  
  7.      {  
  8.           this.name = name;        
  9.      }  
  10.      void getName()  
  11.      {  
  12.           System.out.println(this.name);  
  13.      }  
  14.      public void show()  
  15.      {  
  16.           System.out.println(name+"  "+country);  
  17.      }  
  18.   
  19. }  
  20. class  StaticDemo  
  21. {  
  22.      public static void main(String[] args)  
  23.      {  
  24.           Person p = new Person();  
  25.           p.setName("lisi");  
  26.           p.show();  
  27.           //类名直接调用static修饰的静态成员  
  28.           System.out.println(Person.country);  
  29.      }  
  30. }  
主函数是一个特殊的函数,作为程序的入口,可以被jvm调用

主函数的定义:

public:代表着该函数访问权限是最大的.

static:代表者函数随着类的加载就已经存在.

void:主函数没有具体的返回值.

main:不是关键字,但是是一个特殊的单词,可以被jvm识别.

(String[] args):函数的参数,参数类型字符串类型的数组,args是参数的意思,可以被更改

主函数是固定格式的

jvm在调用主函数时,传入的是new String[0];

例如:

[java] view plaincopy
  1. class MainDemo  
  2. {  
  3.      public static void main(String[] args)//new String[]  
  4.      {  
  5.           String[] arr = new String[]{"haha","xixi","hehe","gaga"};  
  6.           MainTest.main(arr);  
  7.      }  
  8. }  
  9. class MainTest  
  10. {  
  11.      public static void main(String[] args)  
  12.      {  
  13.           for (int x=0;x<args.length;x++)  
  14.           {  
  15.                System.out.println(args[x]);  
  16.           }  
  17.      }  
  18. }  

什么时候使用静态?

从两方面下手:

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

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

当对象中出现共享数据时,该数据被静态修饰.

对象中的特有数据要定义成非静态.

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

当类中的函数(方法)没有访问到非静态数据(变量),

那么该功能可以定义成静态的.

例如:

[java] view plaincopy
  1. class Person  
  2. {  
  3.      String name;  
  4.      public static void show()//这个函数没有访问类中的变量,就用static修饰  
  5.      {  
  6.           System.out.println("haha");      
  7.      }  
  8. }  
  9. class  StaticDemo1  
  10. {  
  11.      public static void main(String[] args)  
  12.      {  
  13.            
  14.           Person.show();  
  15.      }  
  16. }  

静态的应用.

每一个应用程序中都有共性的功能,可以将这些功能抽取独立封装,以便复用.

虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作.发现了问题.

1.对象是用于封装数据的,可是ArrayTool对象并未封装特有数据.

2.操作数组的每一个方法都没有用到ArrayTool对象中的特有数据.

这时就考虑,让程序更严谨,是不需要建立对象的.

可以将ArrayTool中的方法都定义成static,直接通过类名调用即可.

将方法都静态后,可以方便于使用,但是该类还是可以被其他程序建立对象.

为了更严谨,强制该类不能建立对象.

可以通过让构造函数private(私有化),强制该类不能初始化并建立对象.

能隐藏起来的方法都用私有化隐藏起来.

例子:

[java] view plaincopy
  1. class ArrayTool  
  2. {  
  3.      private ArrayTool(){}  
  4.      public static void getMax(int[] arr)  
  5.      {  
  6.           int max = 0;  
  7.           for (int x = 1;x<arr.length;x++)  
  8.           {  
  9.                if (arr[x]>arr[max])  
  10.                {  
  11.                     max = x;                                         
  12.                }                
  13.           }  
  14.           System.out.println("max="+arr[max]);  
  15.      }  
  16.     public static void getMin(int[] arr)  
  17.      {  
  18.           int min = 0;  
  19.           for (int x = 1;x<arr.length;x++)  
  20.           {  
  21.                if (arr[x]<arr[min])  
  22.                {  
  23.                     min = x;  
  24.                }  
  25.           }  
  26.           System.out.println("min="+arr[min]);  
  27.      }  
  28.      public static void selectSort(int[] arr)  
  29.      {  
  30.           for (int x = 0;x<arr.length-1;x++)  
  31.           {  
  32.                for (int y = x+1;y<arr.length;y++)  
  33.                {  
  34.                     if (arr[x]>arr[y])  
  35.                     {  
  36.                          swap(arr,x,y);  
  37.                     }  
  38.                }  
  39.           }  
  40.      }  
  41.      public static void bubbleSort(int[] arr)  
  42.      {  
  43.           for (int x = 0;x<arr.length-1;x++)  
  44.           {  
  45.                for (int y = 0;y<arr.length-x-1;y++)  
  46.                {  
  47.                     if (arr[y]>arr[y+1])  
  48.                     {  
  49.                          swap(arr,y,y+1);  
  50.                     }  
  51.                }  
  52.           }           
  53.      }  
  54.      private static void swap(int[] arr,int a,int b)  
  55.      {  
  56.           int temp = arr[b];  
  57.           arr[b] = arr[a];  
  58.           arr[a] = temp;           
  59.      }  
  60.      public static void printArray(int[] arr)  
  61.      {  
  62.           for (int x = 0;x<arr.length;x++)  
  63.           {  
  64.                if(x == 0)  
  65.                    System.out.print("["+arr[x]+",");  
  66.                else if(x == arr.length-1)  
  67.                     System.out.print(arr[x]);  
  68.                else  
  69.                     System.out.print(arr[x]+",");  
  70.                
  71.           }  
  72.           System.out.println("]");  
  73.      }  
  74. }  

静态代码块static {静态代码块执行语句}

特点:随着类的加载而执行,只执行一次,用于给类初始化,优先于主函数,只有用到了类中的内容才加载类,才执行静态代码块。

*执行顺序: 静态代码块--- 构造代码块---构造函数

示例:

[java] view plaincopy
  1. class  StaticCode  
  2. {  
  3.      static  
  4.      {  
  5.           System.out.println("a");  
  6.      }  
  7. }  
  8. class  StaticCodeDemo  
  9. {  
  10.      public static void main(String[] args)  
  11.      {  
  12.           new StaticCode();  
  13.           System.out.println("b");  
  14.      }  
  15.      static  
  16.      {  
  17.           System.out.println("c");  
  18.      }  
  19. }  
  20. //输出的结果为c,a,b,由此可判断静态代码块在内存中优先主函数加载.  

对象初始化过程

Person p = new Person("zhangsan",20);

这句话都做了什么事情?

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

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

3.在堆内存中给new Person("zhangsan"20)开辟空间,分配内存地址.

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

5.对属性进行显示初始化.

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

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

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

对象调用成员过程,见下图


设计模式:解决一类问题最行之有效的方法

java23种设计模式

单例设计模式

想要保证对象唯一.

1.为避免其他程序过多建立该类对象,先禁止其他程序建立该类对象.

2.还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象.

3,为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式.

这三步怎么用代码体现呢?

1.将构造函数私有化.

2.在类中创建一个本类对象.

3.提供一个方法可以获取到该对象

单例设计模式有两种: 懒汉式和 饿汉式 

[java] view plaincopy
  1. //这个是先初始化对象称为:饿汉式  
  2. //Single类一进内存,就已经创建好了对象.  
  3. //饿汉式为常用形式  
  4. class Single  
  5. {  
  6.      private Single(){}  
  7.     private static Single s = new Single();  
  8.     public static Single getInstance()  
  9.      {  
  10.           return s;  
  11.      }  
  12. }  

[java] view plaincopy
  1. //这个是对象调用才初始化,也叫对象的延时加载,称为:懒汉式  
  2. //Single类进内存,对象还没存在,只有调用了getInstance方法时才建立对象  
  3. class Single  
  4. {  
  5.      private static Single s = null;  
  6.     private Single(){};  
  7.      public static Single getInstance()  
  8.      {  
  9.           if (s == null)  
  10.           {  
  11.                //代表这个方法加锁,只能同时有一个对象进来  
  12.                synchronized(Single.class)  
  13.                {  
  14.                     if(s == null)  
  15.                          s=new Single();  
  16.                }  
  17.           }  
  18.           return s;  
  19.      }  
  20. }  
记住原则:定义单例,建议使用饿汉式.因为饿汉式简单安全,懒汉式多线程的时候容易发生问题。

帮助文档(又叫API帮助文档)的制作:javadoc

制作帮助文档的类必须是public修饰的.

范例:

[java] view plaincopy
  1. /** 
  2. 这是一个可以对数组进行操作的工具类,该类中提供了获取最值,排序等功能. 
  3. @author TMking 
  4. @version V1.1 
  5. */  
  6. public class ArrayTool  
  7. {  
  8.      /** 
  9.      空参数构造函数 
  10.      */  
  11.      private ArrayTool(){}  
  12.      /** 
  13.      获取一个整形数组中的最大值 
  14.      @param arr 接受一个int类型的数组. 
  15.      */  
  16.      public static void getMax(int[] arr)  
  17.      {  
  18.           int max = 0;  
  19.           for (int x = 1;x<arr.length;x++)  
  20.           {  
  21.                if (arr[x]>arr[max])  
  22.                {  
  23.                     max = x;                                         
  24.                }                
  25.           }  
  26.           System.out.println("max="+arr[max]);  
  27.      }  
  28.      /** 
  29.      获取一个整形数组中的最小值 
  30.      @param arr 接受一个int类型的数组. 
  31.      */  
  32.     public static void getMin(int[] arr)  
  33.      {  
  34.           int min = 0;  
  35.           for (int x = 1;x<arr.length;x++)  
  36.           {  
  37.                if (arr[x]<arr[min])  
  38.                {  
  39.                     min = x;  
  40.                }  
  41.           }  
  42.           System.out.println("min="+arr[min]);  
  43.      }  
  44.      /** 
  45.      给一个整形数组进行选择排序 
  46.      @param arr 接受一个int类型的数组. 
  47.      */  
  48.      public static void selectSort(int[] arr)  
  49.      {  
  50.           for (int x = 0;x<arr.length-1;x++)  
  51.           {  
  52.                for (int y = x+1;y<arr.length;y++)  
  53.                {  
  54.                     if (arr[x]>arr[y])  
  55.                     {  
  56.                          swap(arr,x,y);  
  57.                     }  
  58.                }  
  59.           }  
  60.      }  
  61.      /** 
  62.      给一个整形数组进行冒泡排序 
  63.      @param arr 接受一个int类型的数组. 
  64.      */  
  65.      public static void bubbleSort(int[] arr)  
  66.      {  
  67.           for (int x = 0;x<arr.length-1;x++)  
  68.           {  
  69.                for (int y = 0;y<arr.length-x-1;y++)  
  70.                {  
  71.                     if (arr[y]>arr[y+1])  
  72.                     {  
  73.                          swap(arr,y,y+1);  
  74.                     }  
  75.                }  
  76.           }           
  77.      }  
  78.      /** 
  79.      给数组中的元素进行位置置换. 
  80.      @param arr 接受一个int类型的数组. 
  81.      @param a 要置换的位置. 
  82.      @param b 要置换的位置. 
  83.      */  
  84.      private static void swap(int[] arr,int a,int b)  
  85.      {  
  86.           int temp = arr[b];  
  87.           arr[b] = arr[a];  
  88.           arr[a] = temp;           
  89.      }  
  90.      /** 
  91.      打印数组中的元素,打印形式是:[element1,element2,...] 
  92.      @param arr 接受一个int类型的数组. 
  93.      */  
  94.      public static void printArray(int[] arr)  
  95.      {  
  96.           for (int x = 0;x<arr.length;x++)  
  97.           {  
  98.                if(x == 0)  
  99.                    System.out.print("["+arr[x]+",");  
  100.                else if(x == arr.length-1)  
  101.                     System.out.print(arr[x]);  
  102.                else  
  103.                     System.out.print(arr[x]+",");  
  104.                
  105.           }  
  106.           System.out.println("]");  
  107.      }  
  108. }   
dos命令:javadoc -d d:\learn\myhelp -author -version ArrayTool.java



------ ASP.Net+Android+IO开发.Net培训期待与您交流! ------
原创粉丝点击