【转载】 J2SE知识点归纳笔记(三)---Java面向对象 Part 3

注:本文转载自coder-pig

原文请戳:http://blog.csdn.net/coder_pig/article/details/22667533


总体来说小猪的文章写的挺详细,这个家伙挺有耐心的,稍安勿躁,一步步来~吐舌头



Java面向对象   Part  3


前言


在前面的两节中我们对面向对象已经有了差不多的了解了,

而这一节也是Java面向对象部分的一个结尾,

在这一节中我们会对抽象类,接口,修饰符,枚举,封装进行解析;





抽象类


什么是抽象类?

我们将具有共同特点的类进行抽象后得到的一个类,而这个类本身的方法并没有任何具体的实现;

eg:定义一个抽象的动物类,然后定义几个抽象方法(动物共有的方法),比如设置有多少只脚的方法

      public abstract void setFoods();


抽象类的定义:

一般使用abstract关键字修饰  

抽象类:      修饰符  abstract    类名{//类的内容} 

抽象方法:    修饰符  abstract   返回值类型  方法名();


抽象类的使用规则:

①如果一个类有一个抽象方法,那么这个类一定是抽象类;反之,如果一个类是抽象类,但可能包含有非抽象的方法

②如果一个类继承了一个抽象类,那么必须重写抽象类中所有的抽象方法,是所有!所有!如果没有全部实现的话

    那么子类必须也要定义为一个抽象类

③abstract不能和static放在一起,否则会出现错误(因为static不能被覆盖,abstract为了生效,必须被覆盖)

④抽象类可不能定义为最终哦!abstract不能与final共存!

⑤注意区分方法的空实现和方法的抽象

eg:方法的空实现:private void show(){}            方法的抽象,无实现: private void show();

⑥抽象类不能够实例化哦!但是可以new的时候重写里面的抽象方法



抽象类使用实例

代码:

  1. package com.jay.example;  
  2.   
  3.   
  4.   
  5. /* 
  6.  * 该代码是定义一个抽象类,汽车类,定义几个属性和抽象方法 
  7.  * 然后定义客车,吊车类作为它的子类, 
  8.  * 在客车类中即重写抽象方法,也重写了具体方法 
  9.  * 在吊车类中,只是重写具体方法,不重写抽象方法,所以吊车类 
  10.  * 需要被设置为抽象类,否则会报错 
  11.  * */  
  12.   
  13.   
  14. abstract class Car  
  15. {  
  16.     protected String color;  
  17.     protected int sudu;  
  18.       
  19.     //定义一个具体的方法  
  20.     public void speed()  
  21.     {  
  22.         System.out.println("加速");  
  23.     }     
  24.     //定义一个抽象方法,是方法的空实现哦,子类继承时需要覆盖该方法  
  25.     public abstract void useful();  
  26. }  
  27.   
  28. class Truck extends Car  
  29. {     
  30.     public void speed()  
  31.     {  
  32.         System.out.println("卡车起步很慢");  
  33.     }  
  34.     public void useful() {  
  35.         System.out.println("卡车是用于货运的!");  
  36.     }  
  37.       
  38. }  
  39.   
  40.   
  41. //定义吊车类,没有实现抽象方法,所以需为抽象类  
  42. abstract class Crane extends Car  
  43. {  
  44.     public void speed() {  
  45.         System.out.println("吊车走得更加慢!");  
  46.     }  
  47. }  
  48.   
  49.   
  50. public class AbstractDemo {  
  51.     //抽象类可不能直接实例化哦!Car c = new Car()是会报错的  
  52.     //当然可以通过向上转型的规则:Car c = new Track();是可以的  
  53.     public static void main(String[] args) {  
  54.         Truck tr = new Truck();  
  55.         tr.speed();  
  56.         tr.useful();  
  57.         //下面是演示protected修饰的作用于,子类或者同包可见  
  58.         tr.color = "白色";  
  59.         tr.sudu = 40;  
  60.         System.out.println(tr.color + tr.sudu + "km/h");  
  61.     }  
  62.       
  63. }  


运行截图:



代码解析:

该代码演示了抽象类的基本用法,定义抽象类父类Car,定义了一个抽象方法和具体方法

然后在卡车类中都重写了两个方法;在吊车类中仅仅重写了具体方法,所以吊车类需要被设置为抽象类

最后还演示了protected的作用域:子类与同包可见



接口


接口的介绍:

因为Java的数据结构是树型的,所以不像C++那样可以同时继承多个父类;但是Java通过接口和内部类实现了多继承

接口是一种特殊的抽象类,一个类实现一个接口,相当于它继承了一个抽象类


接口的定义:

修饰符  inteface 接口名{"内容"}


接口的实现:

一个类可以在继承一个父类同时实现多个接口,用","分隔

class 类名  extents  父类  implements 接口1,接口2...{}


使用规则:

①一个Java文件中只允许有一个public修饰的类或者接口,且需与文件名同名,是一个!!

②在一个接口中,所有方法都是公开的,抽象的方法!!所有的属性都是公开,静态,常量!

③如果一个类声明实现一个接口,但是没有实现接口中的所有方法,那么这个类必须是抽象类哦!

④接口只关心功能,并不关心功能的具体实现

⑤接口也可以通过extends继承哦!但是依旧需要实现子接口和父接口中的所有抽象方法

⑥接口中的方法可以不写public,但是子类实现接口中的抽象方法时,要写上public,不然会报错哦!


代码示例:


  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 在这个代码中,我们定义了两个父接口,又用一个子接口对两个父接口进行了继承 
  5.  * 同时为子接口又定义了一个抽象方法;然后定义了一个Person实现两个父接口 
  6.  * 重写了两个抽象方法;又定义了一个Worker实现了子接口,但同时也需要把父接口 
  7.  * 中的抽象方法进行覆盖 
  8.  *  
  9.  * */  
  10.   
  11.   
  12. //定义一个说话的接口  
  13. interface Speak  
  14. {  
  15.     void speak();  
  16. }  
  17.   
  18. //定义一个吃饭的接口  
  19. interface Eat  
  20. {  
  21.     void eat();  
  22. }  
  23.   
  24. //定义一个子接口,同时继承说话和吃饭的接口,同时定义一个走路的方法  
  25. interface Walk extends Speak,Eat  
  26. {  
  27.     void walk();  
  28. }  
  29.   
  30. //定义一个Person类,实现说话和吃饭接口,重写接口中的抽象方法  
  31. //子类在实现接口的时候,public修饰符不可以省略,不然会报错  
  32. class Person implements Speak,Eat  
  33. {  
  34.     public void speak()  
  35.     {  
  36.         System.out.println("Person类可以说话");  
  37.     }  
  38.     public void eat()  
  39.     {  
  40.         System.out.println("Person类可以吃饭");  
  41.     }  
  42. }  
  43.   
  44. //定义一个Worker类直接实现walk接口,同时要实现两个父接口中的抽象方法  
  45. class Worker implements Walk  
  46. {  
  47.     public void speak()  
  48.     {  
  49.         System.out.println("Worker类可以说话");  
  50.     }  
  51.     public void eat()  
  52.     {  
  53.         System.out.println("Worker类可以吃饭");  
  54.     }  
  55.     public void walk()  
  56.     {  
  57.         System.out.println("Worker类可以走路");  
  58.     }  
  59. }  
  60.   
  61.   
  62.   
  63.   
  64. public class InterfaceTest {  
  65.       
  66.     public static void main(String[] args) {  
  67.         //实例化两个对象,输出对应结果  
  68.         Person p = new Person();  
  69.         p.eat();  
  70.         p.speak();  
  71.           
  72.         Worker w = new Worker();  
  73.         w.eat();  
  74.         w.speak();  
  75.         w.walk();  
  76.     }  
  77. }  

代码截图:



代码解析:

该代码演示了接口的继承,接口的实现

比较简单,这里就略过了



修饰符详解

访问控制修饰符

public:公有的,被public修饰的部分可以被任何程序访问

protected:受保护的,被它修饰的成员只能由同包中的类或者其子类访问

default(默认):不写修饰符就是默认的,别写上defalut啊!同包与同类可见

private:私有的,是Java实现封装的关键,被修饰的成员变量与方法只能被类本身访问,同包也不行哦!


注意事项:

不能够使用protected和private修饰类;要么用public修饰,要么不加任何修饰符


其他修饰符:

static:静态修饰符

①静态变量:

用static修饰的变量,在所有对象中共享的数据,都指向内存中的同一地址

即,任何对象对改值的修改都会使存储空间的值发生改变


代码演示:

  1. package com.jay.example;  
  2.   
  3. class Test  
  4. {     
  5.     //定义初始的值为3  
  6.     static int a = 3;  
  7. }  
  8.   
  9. public class StaticTest {  
  10.     public static void main(String[] args) {  
  11.         //静态成员变量可以直接通过类名进行访问  
  12.         System.out.println(Test.a);  
  13.         //实例化两个对象,在t1中修改a的值,发现t2中的a的值也发生改变  
  14.         Test t1 = new Test();  
  15.         t1.a = 4;  
  16.         Test t2 = new Test();  
  17.         System.out.println(t2.a);  
  18.           
  19.           
  20.         //输出结果是:  
  21.         //3  
  22.         //4  
  23.         //说明了静态变量都是公用一块内存区域的,任何一个对象  
  24.         //对值的修改,都会改变对应内存区域的值  
  25.     }  
  26. }  

②静态方法:

用static修饰的方法,要注意:

静态方法中,只能够访问静态数据或者直接调用静态方法

可以直接通过类名进行调用

代码演示:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  *因为我们的main方法就是静态的方法 
  5.  *所以我们直接在main方法外定义参数和方法 
  6.  *验证静态方法只能访问静态成员 
  7.  * */  
  8.   
  9. public class StaticTest2 {  
  10.       
  11.     //定义非静态的数据与方法  
  12.     int a = 3;  
  13.     void test(){System.out.println("非静态方法可不能被main调用啊");}  
  14.       
  15.     //定义静态的数据和方法  
  16.     static int b = 4;  
  17.     static void test2()  
  18.     {System.out.println("静态方法被main调用了");}  
  19.       
  20.       
  21.     public static void main(String[] args) {  
  22.           
  23.         //下面两个语句,如果调用了是会报错的,不信可以试试  
  24.         //System.out.println(a);  
  25.         //test();  
  26.           
  27.         System.out.println(b);  
  28.         test2();  
  29.           
  30.     }  
  31. }  

③静态代码块

放在类声明的内部,成员方法与构造方法的外部,该代码块会在该类第一次使用时

执行一次,就不会再执行了,通常是在这里写一些初始化的代码

代码演示:

  1. package com.jay.example;  
  2.   
  3. public class static3 {  
  4.     static  
  5.     {  
  6.         System.out.println("静态代码块,通常用于类的初始化");  
  7.     }  
  8. }  

④复杂的成员的初始化问题

当静态数据,静态代码块,对象成员,构造方法等同时存在时,那么成员的初始化顺序又是怎样呢?

其实,初始化顺序是:(静态变量,静态初始化块) --->(变量,变量初始化块)---->构造器

下面我们通过代码来验证这一规律:

  1. package com.jay.example;  
  2.   
  3.   
  4. public class static3 {  
  5.     public static String staticStr = "静态成员初始化";  
  6.     public String str = "普通成员初始化";  
  7.       
  8.     //构造方法  
  9.     public static3() {  
  10.         System.out.println("构造方法初始化");  
  11.     }  
  12.       
  13.     //普通的初始化块  
  14.     {  
  15.         System.out.println(str);  
  16.         System.out.println("普通的初始化块");  
  17.     }  
  18.       
  19.     //静态的初始化块  
  20.     static   
  21.     {  
  22.         System.out.println(staticStr);  
  23.         System.out.println("静态的初始化块");  
  24.     }  
  25.       
  26.       
  27.     public static void main(String[] args) {  
  28.         static3 st = new static3();  
  29.     }  
  30. }  

运行截图:




final:最终修饰符

使用方法


①使用final修饰属性(变量),此时的属性为常量;Java中利用public static final int AGE = 10;对常量进行标识

②空白final变量(没初始化的):空白的final数据成员必须在构造方法中进行初始化,否则会报错

③final常量作为方法的参数,只能够对final进行简单的引用,可不能改变常量的值哦!

④用final来修饰方法:那么该方法为一个不可覆盖的方法,如果父类有final修饰的方法,那么子类继承同一个方法

⑤用final来修饰类:那么该类不可以被继承,final类没有子类;同时该类中所有的方法都默认为final

⑥final并不涉及继承,继承取决于类的修饰符是public还是其他,是否可以继承取决于该类是否对其子类可见

    如果一个方法前有private或static的修饰符,那么系统在前面自动地加上final修饰



abstract:抽象修饰符

被abstract修饰的类为抽象类,修饰的方法为抽象方法


transient:

用于修饰不想序列化,持久化的成员


volatile:

保证可见性和防止重排序,用的比较少,是并发操作那块的



枚举类型

枚举解析:

①作为jdk 1.5 后引入的枚举,用来代替以前定义多个同类型常量的public final static 

②用enum表示,作用类似于class关键字;

③构造方法不要用public修饰

④变量和方法的定义需要在枚举值的后面!!!



用法示例:

简单的枚举:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 本程序演示的是枚举的最简单用法 
  5.  * 定义枚举Color有三个值,演示了switch和增强for循环遍历枚举 
  6.  * 中所有的原始的方法 
  7.  * */  
  8.   
  9. enum Color  
  10. {  
  11.     BLUE,RED,YELLOW;  
  12. }  
  13.   
  14. public class EnumTest {  
  15.     public void printColor(Color color)  
  16.     {  
  17.         switch(color)  
  18.         {  
  19.             case BLUE:  
  20.             System.out.println("输出蓝色!");  
  21.             break;  
  22.               
  23.             case RED:  
  24.             System.out.println("输出红色!");  
  25.             break;  
  26.               
  27.             case YELLOW:  
  28.             System.out.println("输出黄色!");  
  29.             break;  
  30.         }             
  31.     }  
  32.     public static void main(String[] args) {  
  33.         EnumTest test = new EnumTest();  
  34.         test.printColor(Color.BLUE);  
  35.         test.printColor(Color.RED);  
  36.         test.printColor(Color.YELLOW);  
  37.           
  38.         //当然也可以直接用增强for循环来遍历枚举中所有的值:  
  39.         //可以通过values()方法获得枚举的数组  
  40.         for(Color c : Color.values())  
  41.         {  
  42.             System.out.println(c);  
  43.         }  
  44.     }  
  45. }  

运行截图:




深一步的使用:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 本代码演示的是枚举类的进一步使用 
  5.  * 和类一样,枚举可以定义自己的属性和方法,但是 
  6.  * 必须写在枚举列表的后面,不然会报编译时错误 
  7.  * */  
  8.   
  9.   
  10.   
  11.   
  12. public class EnumTest2 {  
  13.       
  14.     public enum Color  
  15.     {  
  16.         //枚举可以像一般的类一样添加方法和属性  
  17.         Red("红色"),BLUE("蓝色"),YELLOW("黄色");  
  18.           
  19.         //构造方法,不要写public修饰!  
  20.         Color(String value)  
  21.         {  
  22.             this.value = value;  
  23.         }  
  24.           
  25.         //定义一个成员变量  
  26.         private final String value;  
  27.           
  28.         //定义一个获取后面值得方法  
  29.         public String getValue()  
  30.         {  
  31.             return value;  
  32.         }  
  33.           
  34.           
  35.     }  
  36.       
  37.   
  38.       
  39.     public static void main(String[] args) {  
  40.         EnumTest2 test = new EnumTest2();  
  41.         //可以通过for循环调用获得枚举中所有的值  
  42.         for(Color color : Color.values())  
  43.         {  
  44.             System.out.println(color);  
  45.             System.out.println(color.getValue());  
  46.         }  
  47.           
  48.         //可以通过ordinal获得枚举值在枚举中的索引位置,从0开始的  
  49.         System.out.println(Color.BLUE.ordinal());  
  50.           
  51.         //枚举默认实现了java.lang.Comparable接口,可以直接调用compareTo对枚举值进行比较  
  52.         //这里Red在Blue前面,所以是-1  
  53.         System.out.println(Color.Red.compareTo(Color.BLUE));  
  54.           
  55.     }  
  56. }  

运行截图:



小结:

在这里,我们仅仅演示了enum枚举类型的两种基本用法,

如果有兴趣深入研究枚举的可以参考以下文档:Java枚举类型详解

http://pan.baidu.com/s/1o6qHLUy



封装:

将数据与数据操作绑定到一个类中,这样的方法就保证了程序中的数据不会受到外部代码的影响
在Java中通常是将属性设置为private,然后再类中设置getXxx()和putXxx()方法对数据进行操作
从而保证代码的独立性,而且能够比较容易地对程序进行维护和修改




总结:

在面向对象的最后一节,在这一节中我们对抽象类,接口
各种修饰符,枚举和封装进行了深入的解析
Java面向对象知识点到此结束,我们学会的仅仅是基础
需要在编程中进行巩固,大家要做下相关的编程题目
做多了,知识点也就记得了!



如果文中有遗漏,错误,好的建议;
望读者指出,万分感激!!(*^__^*) 嘻嘻……


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值