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

注:本文转载自coder-pig

原文链接请戳:http://blog.csdn.net/coder_pig/article/details/22296069



今天虽然是五一假期,但是本人属于密集恐惧症-阳光恐惧症-社交恐惧症,所以宅在家里看看书,也是不错滴选择,紧接着上篇文章,深入学习下面向对象。可怜加油加油~


Java面向对象 Part 2

前言

在上一节中,我们对面向对象进行了

初步的解析,掌握了类和对象的概念

以及定义,实现,在这一节中,我们将对面向对象的灵魂

继承与多态进行剖析,同时也会讲解下4种内部类的使用

好了,废话不多说!



继承:


继承的理解:

比如:城管,公务员,学生,警察,他们的共性都是人,所以人类是他们的父类,而他们是人类的子类;

子类拥有父类的所有属性,比如姓名,年龄等,同时子类也衍生了一些自己的特性:比如城管拥有暴力执法的属性...

呃,这里说笑而已= =,应该不会给查水表吧



继承的方式:

子类  extends  父类  

eg:  class Student extends Person{}


继承的注意事项:

Java的数据结构:树形,所以不像C++一样可继承多个父类,只能单继承;Java通过接口和内部类实现多继承

父类的私有属性也可以继承,但是不可以直接进行访问,只能够通过父类的方法进行访问

子类如果想调用父类的构造方法要使用super(参数),否则会提示找不到

Object类是所有类的父类!!



子类构造对象的顺序:

先构造父类的对象,再构造子类对象:

递归构造父类对象,顺序地调用本类成员的赋初值语句,本类的构造方法


继承代码示例:

代码解析:定义一个父类与子类,跟踪对象的构造顺序,同时在子类中调用父类的方法和重写父类方法


Father.java


  1. package com.jay.example;  
  2.   
  3. public class Father {  
  4.       
  5.       
  6.     //定义两个私有变量,子类无法直接访问  
  7.     private String name;  
  8.     private int age;  
  9.       
  10.     //一个好的编程习惯是写上默认的缺省的构造方法  
  11.       
  12.     //在下面的两个构造方法中我们都加入一个println语句  
  13.     //以此来跟踪构造对象的过程  
  14.       
  15.     public Father()  
  16.     {  
  17.         System.out.println("父类无参构造方法被调用");  
  18.     }  
  19.     public Father(String name,int age)  
  20.     {  
  21.         this.name = name;  
  22.         this.age = age;  
  23.         System.out.println("父类的有参构造方法被调用");  
  24.     }  
  25.       
  26.     /*设置这些get和set方法是因为封装 
  27.     *我们在子类中想访问父类的私有元素就只能够这样了 
  28.     *通过在父类暴露一个借口提供给子类访问 
  29.     */  
  30.     public String getName() {  
  31.         return name;  
  32.     }  
  33.     public void setName(String name) {  
  34.         this.name = name;  
  35.     }  
  36.     public int getAge() {  
  37.         return age;  
  38.     }  
  39.     public void setAge(int age) {  
  40.         this.age = age;  
  41.     }  
  42.       
  43.       
  44.     /* 
  45.      * 这个方法是想在子类中调用的 
  46.      * */  
  47.       
  48.     public void printMessage()  
  49.     {  
  50.         System.out.println(name + "今年" + age + "岁");  
  51.     }  
  52.       
  53.     /* 
  54.      * 这个方法是供子类覆盖重写的 
  55.      * */  
  56.     public void test()  
  57.     {  
  58.         System.out.println("我是父类的test");  
  59.     }  
  60.       
  61. }  


Son.java


  1. package com.jay.example;  
  2.   
  3. public class Son extends Father{  
  4.     //定义子类自己的属性  
  5.     private int grade;  
  6.       
  7.     /* 
  8.      * 同理,为两个构造方法添加println语句用于跟踪构造对象的顺序 
  9.      * */  
  10.     Son(){        
  11.         System.out.println("子类的无参构造方法被调用了");  
  12.     }  
  13.       
  14.     Son(String name,int age,int grade){  
  15.         //通过super关键字调用父类的构造方法,进行参数传递  
  16.         super(name,age);  
  17.         this.grade = grade;  
  18.         System.out.println("子类的有参构造方法被调用了");  
  19.     }  
  20.   
  21.       
  22.     public int getGrade() {  
  23.         return grade;  
  24.     }  
  25.   
  26.     public void setGrade(int grade) {  
  27.         this.grade = grade;  
  28.     }  
  29.       
  30.     //调用父类的方法访问父类的私有变量  
  31.     public void printMsg()  
  32.     {  
  33.         System.out.println(getName()+"小学生今年"+getAge()+"岁,读"+ grade + "年级");  
  34.     }  
  35.       
  36.     //重写父类的test方法  
  37.     public void test()  
  38.     {  
  39.         System.out.println("我是子类的test");  
  40.     }  
  41. }  


ExtendTest.java


  1. package com.jay.example;  
  2.   
  3. public class ExtendTest {  
  4.       
  5.     public static void main(String[] args) {  
  6.           
  7.         Son son1 = new Son();  
  8.         son1.setName("大猪");  
  9.         son1.setAge(25);  
  10.         son1.printMessage();  
  11.           
  12.         System.out.println();  
  13.           
  14.         Son son2 = new Son("小猪",20,1);  
  15.         son2.printMsg();  
  16.           
  17.         System.out.println();  
  18.         son2.test();  
  19.     }  
  20.       
  21. }  


输出结果:



结果分析:

①从上面我们可以知道"先有父亲,后又儿子";创建子类对象时会先创建一个父类对象,

不用我们自己实例化父类对象,系统自动创建;

②我们可以通过super()访问父类构造方法或者用super.XXX访问父类的同名成员

③子类可以重写父类中的方法成员



super关键字:

子类中访问父类的同名成员,用super语句向父类构造方法传,那么super(参数)方法要放在第一句 





多态:


多态的分类:


 编译时多态(方法重载)  OverLoading


在同一个类中可以定义多个同名的方法,各个方法的参数表一定不同(参数个数,类型)

返回值可以不同;比如构造方法的重载就是编译时的多态了


代码示例:


  1. package com.jay.example;  
  2.   
  3. class HeHe  
  4. {  
  5.     public HeHe(){}  
  6.       
  7.     //这里重写几个一样的show方法  
  8.     public void show()  
  9.     {  
  10.         System.out.println("①重写");  
  11.     }     
  12.     public void show(int a)  
  13.     {  
  14.         System.out.println("②重写");  
  15.     }     
  16.     public void show(float a)  
  17.     {  
  18.         System.out.println("③重写");  
  19.     }  
  20.     public void show(int a,float b)  
  21.     {  
  22.         System.out.println("④重写");  
  23.     }  
  24. }  
  25.   
  26.   
  27. public class OverLoadingTest  
  28. {  
  29.     public static void main(String[] args) {  
  30.         HeHe he = new HeHe();  
  31.         he.show();  
  32.         he.show(1);  
  33.         he.show(0.1f);  
  34.         he.show(20.2f);  
  35.     }  
  36. }  


运行结果:





运行时多态:(方法重定义/覆盖)    OverRidding


运行时多态 = 继承  +  重定义  + 动态绑定


方法覆盖:

子类方法与父类方法名,参数相同,返回值类型也相同;

规律:不能回避比父类方法更多的异常,子类访问控制必须必父类方法更公开


向上转型规则(upcasting)

Animal a = new dog();

Dog  d = (Dog)a;


这里有个问题:

如果调用a的叫方法,jiao()那么,调用的会是Animal的叫还是Dog的叫?

答案是:狗叫,new后面是什么类,动态类型就是什么类

不懂没关系,看下面的演示代码


  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 代码解析: 
  5.  * 在代码中我们定义了三个类,父类,子类以及一个测试类 
  6.  * 我们要验证的是Father f = new Son(123);当我们调用相同名称的方法时 
  7.  * 是以父类的方法还是以子类的方法为准 
  8.  * 从代码可知,我们对print方法进行了重载 
  9.  * */  
  10.   
  11.   
  12. class Father {  
  13.     public Father() {  
  14.         System.out.println("父类构造方法打印前\t");  
  15.         print();  
  16.         System.out.println("父类构造方法打印后\t");  
  17.     }  
  18.       
  19.     public void print()  
  20.     {  
  21.         System.out.println("父类的打印方法\t");  
  22.     }  
  23. }  
  24.   
  25. class Son extends Father{  
  26.     int flag;  
  27.     public Son(int flag) {  
  28.         this.flag = flag;  
  29.         System.out.println("子类的构造方法\t"this.flag);  
  30.     }  
  31.       
  32.     public void print()  
  33.     {  
  34.         System.out.println("子类打印方法\t" + flag);  
  35.     }  
  36. }  
  37.   
  38.   
  39. public class OverRridingTest  
  40. {  
  41.     public static void main(String[] args) {  
  42.           
  43.         Father f = new Son(123);  
  44.     }  
  45. }  


运行结果:




分析总结:

从上面的代码,相信大家对运行时的多态有更深一步的了解了;

第二行输出 0 ,说明了调用的是子类的print,这也说明了new后面什么类型,动态类型就是什么类型






内部类:

内部类有:成员内部类,静态内部类,局部内部类,匿名内部类四种


成员内部类:

将一个类嵌套定义在另一个类中,包含内部类的类叫做外部类

内部类可以直接访问外部类的成员和方法

注意:访问内部类的话需要先创建外部类对象,接着才可以用它来创建内部类对象


代码示例:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 该代码演示了如何访问内部类,有以下两种方式 
  5.  * ①在外部类中直接实例化内部类,并且调用内部类的方法或者参数 
  6.  * ②在测试类中先实例化外部类,在实例化内部类,从而调用对应的方法 
  7.  * eg:注意是这样写哦!Outer.Inner iner = out1.new Inner(); 
  8.  * */  
  9.   
  10.   
  11. class Outer  
  12. {  
  13.     String outString = "外部类的成员变量被访问";  
  14.     //在该方法中实例化内部类,并且调用show方法  
  15.     void showinner()  
  16.     {  
  17.         Inner in = new Inner();  
  18.         in.show();  
  19.     }  
  20.       
  21.     //创建一个成员内部类  
  22.     class Inner  
  23.     {  
  24.         void show()  
  25.         {  
  26.             System.out.println("内部类的show方法被调用!");  
  27.             System.out.println(outString);  
  28.         }  
  29.         //用于演示在其他类中使用内部类的方法  
  30.         void test()  
  31.         {  
  32.             System.out.println("在测试类中访问内部类的方法");  
  33.         }  
  34.     }  
  35. }  
  36.   
  37.   
  38.   
  39. public class InnerTest {  
  40.   
  41.     public static void main(String[] args) {  
  42.           
  43.         Outer out1 = new Outer();  
  44.         out1.showinner();  
  45.         //直接实例化内部类,注意写法!  
  46.         //如果写成Outer.Inner iner = new Outer.Inner();是错的哦!  
  47.         Outer.Inner iner = out1.new Inner();  
  48.         iner.test();  
  49.           
  50.     }  
  51. }  

运行结果:



静态内部类:

是成员内部类的一种,但又是特殊的,他具有以下特性:

静态内部类只能够访问外部类的静态成员;

创建内部类对象不需要外部对象,直接:new 外部类名.内部类的构造方法


代码示例:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 该代码演示了静态内部类的使用 
  5.  * 内部类对象只能够访问外部类对象中的静态成员 
  6.  * 如果调用非静态成员会报错 
  7.  * 也演示了两种实例化静态内部类成员的办法 
  8.  * 直接new 外部类.内部类即可 
  9.  * */  
  10.   
  11.   
  12. class Draw  
  13. {     
  14.           
  15.     public static int k = 250;  
  16.     public void print()  
  17.     {  
  18.         Pen p = new Pen("猪头");  
  19.         p.speak();  
  20.     }  
  21.       
  22.       
  23.     static class Pen  
  24.     {  
  25.         int i = 100;  
  26.         String name ;  
  27.           
  28.         public Pen(String name)   
  29.         {  
  30.             this.name = name;  
  31.         }  
  32.           
  33.         void speak()  
  34.         {  
  35.             System.out.println(name + "你好!\t"+k);  
  36.         }  
  37.     }  
  38. }  
  39.   
  40.   
  41. public class StaticTest {  
  42.     public static void main(String[] args)   
  43.     {  
  44.           
  45.         Draw d = new Draw();  
  46.         d.print();  
  47.           
  48.         Draw.Pen pen= new Draw.Pen("呵呵");  
  49.         pen.speak();  
  50.     }  
  51. }  

运行截图:




局部内部类:

与成员内部类不同,局部内部类是存在于类中的某个局部,可能是在某个方法或者某个块语句中

是用的最少的一种内部类,和局部变量一样,不能够被public,protected,private和static修饰

只能够访问方法中定义的final类型的局部变量

只能够在方法中生成局部内部类的对象并且调用它的方法


实例代码:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 该代码演示的是 
  5.  * 在外部类的方法中创建一个局部内部类 
  6.  * 同时需要在方法中实例化这个内部类对象 
  7.  * 而内部类可以访问外部类成员和方法中final修饰的成员变量 
  8.  * */  
  9.   
  10. class Outer  
  11. {  
  12.     int a = 1;  
  13.       
  14.     public void show()  
  15.     {  
  16.         int b = 2;  
  17.         final int c = 3;  
  18.         //定义一个局部内部类  
  19.         class Inner  
  20.         {  
  21.             public void inPrint()  
  22.             {  
  23.                 System.out.println("局部内部类的方法:");  
  24.                 //可以访问外部类中的变量  
  25.                 System.out.println(a);  
  26.                   
  27.                 //system.out.printf(b);这里可是会报错的哦!  
  28.                   
  29.                 //可以访问方法中的final的变量  
  30.                 System.out.println(c);  
  31.             }  
  32.         }  
  33.           
  34.         //需要在方法中实例化内部类对象哦!  
  35.         new Inner().inPrint();  
  36.     }  
  37.   
  38. }  
  39.   
  40.   
  41.   
  42. public class LoaclTest {  
  43.     public static void main(String[] args) {  
  44.         //创建外部类对象,同时调用外部类的方法  
  45.         Outer out = new Outer();  
  46.         out.show();  
  47.     }  
  48. }  


匿名内部类:

没有名称的内部类,必须是非静态的类

通常是隐式地继承一个父类或者实现一个接口

用的比较多的是作为某个方法的参数,如Java中的GUI事件编程,android中事件处理机制

比较简单,看下下面android中为按钮设置点击事件的方法就了解了


  1. btnregister.setOnClickListener(new OnClickListener() {  
  2.               
  3.             @Override  
  4.             public void onClick(View arg0) {  
  5.                 Intent it = new Intent(LoginActivity.this,RegisterActivity.class);  
  6.                 startActivityForResult(it, 0x123);  
  7.                 overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);  
  8.             }  
  9.         });  

代码解析:

代码实现了为按钮设置一个点击事件,参数,直接是通过new OnClickListener(){}这里实例化一个匿名内部类对象

作为参数,并且重写OnClickListerner接口中的onClick()方法




总结:

在这一节中,我们深入面向对象,学习了面向对象的核心部分

继承与多态,并且了解了四种内部类的使用

内容不多,读者写相关代码体现其中的奥秘!


好的,最后谢谢各位读者的支持

如果有什么纰漏,错误,不好的,或者什么好的建议;

望读者指出,不甚感激,(*^__^*) 嘻嘻……!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值