黑马程序员----java基础之面向对象(2)

时间:2022-02-28 12:07:23

                                                              ------- android培训java培训、期待与您交流! ----------

 

李小龙__光是知道是不够的,必须加以运用;光是希望是不够的,非去做不可.  学习java就像练武术,不用是会荒废的.

 

    <1> 面向对象之继承

         类与类之间的关系  1依赖  2.聚合  3.继承   上个帖子的继承,这个帖子专门来讲.

 

          

继承的由来

                           

                            将多个类中公共的内容向上抽取产生了父类(基类  超类)

                            这个被抽取的类叫子类

 

                            通过这种方式我们可以节省代码

                                              

继承的格式

                  

                            class子类  extends 父类似{

                           

                            }

                           

                            ********************************

                            通过继承,子类自动拥有父类的所有非private成员。

 

                            也可以说private成员子类可以继承,但是不能使用。因为private限定使用的范围。

                            ********************************

 

继承的好处

 

                            继承的出现提高了代码的复用性。

                            继承的出现让类与类之间产生了关系,提供了多态的前提。

 

Java的继承规则

单继承

java中只支持单继承,一个父类可以派生多个子类.

 

                            为什么只支持单继承?就是为了避免混淆

                                     classFather{

                                              void fun(){}

                                               voidmethod(){}

                                     }

                                     classAFather{

                                               voidfun(){}

                                     }

                                     classASon extends Father,AFather{

                                               //当前ASon有两个父类 Father ,AFather,那么对于ASon子类来说

                                               它里面存在fun方法,这个方法是从哪一个父类继承?为了避免这种

                                               情况的存在,java中只允许单继承

                                     }

                                     classBSon extends Father{

                                     }

                                     说难听点就是一个儿子只能有一个爹,一个爹可以有多个儿子,呵呵,明白就好,别外传.

 

多重继承

         java中支持多重继承

         classGradeFather{

                                     voidfun(){}

                            }

                            classFather extends GradeFather{

                                     voidfun(){} //这个方法是从GradeFather中继承的

                            }

                            classSon extends Father{

                                     //当前Son这个类也可以看成是GradeFather的间接子类.

                                     voidfun(){} 这个方法是从Father继承的。

                            }

                  

                   通过多重继承产生了一个继承的体系,怎样使用体系

                           

                            上层的类中定义的行为对于这个体系来说,所有下层的类中都包含.

 

                            对我们来说在学习一个体系时,从上层来观察.通过上层能了解整个体系的基本行为.

 

                            真正使用时,使用的最下层的类。

 

                            上层:标识的是整个体系的功能

                            下层:标识的是特性的功能(根据具体的要求来选择)

 

如何使用继承

记住一句话: 不要为了继承而继承(不要为了使用某个属性或方法去特意的继承)

我们什么时候使用继承,要进行具体的分析,继承其时是一种is关系

 

举例:

                            class动物{

                           

                            }

 

                            class哺乳动物{

                                     voideat();

                            }

 

                            class犬科 extends 哺乳动物{

                            }

                            class猫科 extends 哺乳动物{

                           

                            }

                            class狗 extends 犬科{}

 

                            class狼 extends 犬科{}

 

                            class猫 extends 猫科{}

 

                            class虎 extends 猫科{}

 

                            class蝙蝠 extends 哺乳动物{}

 

                            class跳蚤{

                                     //如果它也有一个吃的行为,就不应该继承犬科,猫科,也不能继承哺乳动物。

                            }

继承中的构造方法

首先:构造方法不能被继承

 

                            通过下面代码发现,当子类对象实例化时Son son=new Son(),父类构造先执行了,然后执行的是子类构造.

                            //父类

                            classFather

                            {

                                     Stringname;

                                     Father(Stringname){

                                               super();//执行Object父类的无参构造方法

                                               System.out.println("father构造");

                                     }

                                     Father(intage){

                                     }

                                     Father(){}

                            }

                            //子类

                            classSon extends Father

                            {

                                     Stringsex;

                                     Son(){

                                               //super();  //执行Father父类的无参构造方法          

                                               super("tom");//执行Father父类的字符串参数的构造方法

                                               System.out.println("son构造");

                                     }

                            }

                            为什么出现这种情况?

                                    

                                     因为所有的构造方法中默认执行的第一句话都是super();

 

                                     super();它代表的意思是执行父类的无参构造方法。

 

                                     java中的所有类都有一个默认的父类 Object类,它是所有java类的父类.

 

                            父类的构造方法执行,做了什么事情?

                                    

                                     父类的构造方法执行的目的是为了帮助子类对象实例化.

                            代码分析:是因为每一个构造方法中有super()

                            原理分析:父类构造方法被执行是帮助子类对象实例化

 

                            super()默认存在于每一个构造方法的第一句,写与不写一样

                            如果父类中不存在无参构造,那么必须在子类中指定通过哪一个构造方法去实例化对象

                            super(参数);

 

                            在构造方法中的super()与this()

                                     super()它的作用:执行父类的构造方法

                                     this()  它的作用:执行本类的构造方法

                                     super()与this()在使用时注意事项

                                              

                                               1.它们只能出现在构造方法中

                                               2.它们如果要出现,必须是构造方法中的第一句.                      

                                               3.super()与this()不能共存.

                                               为什么中只能出现一次,并且出现在第一行,因为如果要出现了多次,就会执行多次构造方法.

继承中的成员属性

                           

                            如果子类中存在与父类中重名的成员属性

                           

                            在子类中有一个方法,它显示这个重名的属性

                            this存在成员方法中作用:用来区*部与成员属性

                            super存在成员方法中作用:用来区分子类与父类中重名的成员

                            classFather

                            {

                                     Stringname="tom";//父类成员变量                       

                            }

                            classSon extends Father

                            {

                                     Stringname="james"; //子类成员变量

                                     publicvoid show(){

                                               Stringname="tony"; //局部变量

                                              

                                               System.out.println(name);  //局部变量name

 

                                               System.out.println(this.name);//本类中的name 属性

 

                                               //要得到被子类隐藏的父类中的name属性

 

                                               System.out.println(super.name);//通过super可以得到父类中的name属性

                                     }

                            }

继承中的成员方法   

                                    

                            重写:子类中存在一个与父类中一样的方法

                                 一样的意思是返回值类型,方法名,参数列表都一样。

                           

                            重写的作用:通过重写可以将父类中的方法进行功能扩展.

                            重写的注意事项:

                                     1.静态只能覆盖静态

                                     2.重写的方法的权限修饰符要大于等于被重写的方法

                                     3.私有的方法不能被重写.

                           

                            关于多态的两种表现形式:重写与重载

 

                            重写与重载的区别?

                                      重载:一个类中具有相同的方法名,参数的类型,个数,排列顺序不同产生了重载.

                                     重写:子类中有一个与父类一样的方法,方法的返回值类型,方法名,参数列表一样。

                  

                            重写的作用:可以在子类中对父类的方法进行功能扩展.

 

                            在重写的方法内如果要使用父类中的方法可以使用super调用。

final使用

                  

                   final是一个修饰符

                  

                   修饰类: 代表这个类不能被继承

                            String类就是一个final类

                   修饰方法: 代表这个方法不能被重写

                  

                   **修饰属性:代表这个属性是一个常量  在定义时,一般属性名都要大写。final double PI=3.14;

                   在实际操作中什么时候使用final修饰属性

                            例如在开发中求圆的面积会使用圆周率,它的值就应该是3.14,而不能改变。

                            这个时候这个变量就应该是final的。

                            我们做的扑克牌程序,它的花色与值也是不能改变的,也应该是final的。

                  

                   小练习:

                   classFinalDemo{

                           

                            finalint i;  //如果 final int i=1;这种情况也会出问题,构造不能再赋值

 

                            FinalDemo(inti){

                                     this.i=i;

                            }

                            publicstatic void main(String[] args){                        

                                     FinalDemofd=new FinalDemo(10);

                                     //fd.i=100;//也会出问题.原因:构造方法中赋值了,不能再改变.

                                     System.out.println(fd.i);

                            }

                   }

                  

                   如果当前i没有初值,那么我们可以在构造方法中对其进行一次赋值操作。

                   当对象产生后就不能在对其进行赋值操作。

构造代码块与局部代码块

 

         什么叫代码块  {  } 一对大括号中的内容叫代码块

        

         什么叫构造代码块代码块声明在类的成员位置上叫构造代码块

 

         什么局部代码块  代码块声明在方法内

 

         构造代码块的作用: 它优先与构造方法执行,在构造代码块中的内容是所有的构造方法都要执行的内容。

 

         局部代码块的作用:限定局部变量的生命周期

static关键字

        

         它随着类的加载而加载,优先于对象产生。放在方法区的静态区内。static修饰的成员,可以通过类名去调用。

 

         static是一个修饰符

 

修饰属性  叫类属性  静态属性

                           

                            特点:1.在内存中只有一个,所有的对象共享。

                                 2.它存在于内存的方法区的静态区域内,它是随着类的加载而加载的。它的生命周期

                                     与类的类的生命周期一样。

                                 3.对于静态(类)属性  我们在使用时一般不使用引用(对象)调用,而是使用 类名.静态属性。                    

 

                            什么时候使用static属性?

                                     static修饰的属性在内存中只有一个,比较节省资源.

                                     这个数据所有的对象的值都一样。

                                     当前这个属性是用来描述的类的相关信息,这个属性也应该是static.

 

                            静态属性与实例属性的区别

                                     1.内存空间  静态属性在方法区的静态区域内   实例属性在堆内

                                     2.生命周期  静态属性是随着类的加载而加载,它与类的生命周期一样

                                                   实例属性它是属于对象的与对象的生命周期一样。

                                    

                                     3.共享:  静态属性在内存中只有一个,所有对象使用的是同一个。

                                                实例属性属于每个对象,每个对象有自己的实例属性

 

                                     4.调用:  静态属性可以使用   引用(对象).静态属性   也可以使用  类名.静态属性  在实际操作中类名调用使用比较多。

                                                实例属性   引用(对象).实例属性  

修饰方法 

                   static修饰的方法   类方法   静态方法

                   static方法也是随着类的加载而加载

                   调用时也可以通过类名.类方法   引用(对象).类方法名

                   注意事项:

                            1.在static方法内只能使用static成员。报错:Demo4.java:17: 错误: 无法从静态上下文中引用非静态

                            2.在static方法内不能使用this,super这样的关键字

                                     原因:this指代某个对象,对于static方法它是随着类的加载而加载的。

                                          这个时候对象还没产生,所以不能使用this

 

                   在非静态方法内使用静态成员是可以的。

 

                   静态方法什么时候使用?

                            如果当前方法内所使用的属性不是成员属性,这时这个方法应该是static。

                            当前类是一个工具类,其中的方法完成的是一个独立的功能.

                  

                   三种方法  类方法   实例方法   构造方法各自的特点

 

                            1.结构: 类方法  使用static修饰的      可以有返回值 如果没有使用void

                                    实例方法  使用非static修饰的   可以有返回值 如果没有使用void

                                     构造方法  它没有修饰符(权限除外)  没返回值 void也没有

                           

                            2.应用: 类方法     它一般描述的是与成员属性无关的操作。

                                     实例方法   它描述的是与成员属性有关的操作。

                                     构造方法   它是用来创建对象。

 

                           

                            3.调用: 类方法     可以使用类名调用也可以使用引用(对象)调用

                                     实例方法   只能使用引用(对象)调用

                                     构造方法   想要执行,创建对象。

 

                            4.内存空间:

                                               类方法:方法区的静态区域内

                                               实例方法构造方法都是在方法区。

主方法也是static(了解)

                  

                   publicstatic void main(String[] args){  }

 

                   public  权限修饰符

                   static  静态方法  主方法在被jvm调用时直接通过类名调用,不需要对象 

                   void   jvm不需要主方法的返回值。

                   main    固定

                   String[]args  参数   命令行参数  学习中做测试

 

 

                   主方法是由jvm调用,我们可不可以调用哪?

 

                            主方法是一个静态的方法,可以通过类名去调用。

类的组成

 

                   class类名{

                           

                            成员属性 :类属性(static修饰的)   实例属性.(非static修饰的)

                                     在一些java书中所说的成员属性一般指的都是实例属性。

 

                            成员方法:类方法(static修饰)    实例方法(非static修饰)

 

                            构造方法

                   }

 

静态代码块

                  

                   static{} 声明在类中。

 

                   优先于构造代码块,构造方法执行,并且只执行一次。

 

                   静态代码块中定义什么内容?静态代码块什么时候使用?

 

                            静态代码块中所使用的成员也必须是静态的。

                            对于静态代码块它是用来描述类的相关信息。并且只执行一次的内容。

 

                            对于比较消耗资源,然后加载一次就可以使用内容。放到静态代码块中。

                            对于程序在启动时需要优先加载的内容,也可以放入到静态代码块中。

 

javadoc命令使用

 

         /**

                   文档注释 java特有的。

         */

 

         我们可以通过javadoc.exe命令将我们程序中的文档注释抽取出来形成 xxx.html文件

 

         javadoc-d  c:\a

 

         -dc:\a 作用是将从程序中的文档抽取的文件放入到指定的目录(c:\a)下。

 

         @param  生成参数

         @return生成返回值

         @author  生成作者

         @version生成版本

 

         javadoc-d  目录  源文件.java -author –version (要生成作者与版本格式)

 

举例:       打开cmd        javadoc -d  d:\a  Demo.java-author –version   将Demo.java 文件中的文档注释抽取出来放入D盘的a文件夹下形成html文件

 

单实例

        

         使用模式的好处:可以让我们代码更健壮,安全,结构更严禁。

 

         单实例设计模式:它解决的问题是保证对象唯一化.

         怎样能保证在堆内存中只有一个SingleTon对象,所有人使用的是同一个?

                  

                   分析:

                            1.不能让外部任意new出来SingleTon对象.

                            2.对外提供公共静态的方法可以获得本类对象.

                                     为什么?因为如果是实例方法需要对象调用

                            3.在本类中声明一个私有的静态本类对象

                  

                   代码实现步骤:

                            1.将构造方法私有化  private 构造

                            2.创建公共static方法返回本类对象  public static SingleTon getInstance(){returns;}

                            3.在本类中创建一个本类的静态对象  private static SingleTons=new SingleTon();

        

                   单实例模式在实际开发中什么时候使用?

                                    

                                     例如在开发中我们要连接数据库,对于java连接外部设备时是比较消耗资源的。

                                     为了节省资源,我们就可以使用单实例模式得到一个连接数据库的对象。

                                     所有人要想操作时,都使用同一个对象。

 

                                     例如DataSource对象它的获得就是一个单实例      

                   //单实例---饿汉式(非延迟加载)

                   classSingleTon

                   {

                            //3.在本类中定义一个本类的对象

                            privatestatic SingleTon s=new SingleTon();

                            //1.私有化构造

                            privateSingleTon(){}

 

                            //2.提供公共的静态方法可以获得本类对象

                            /*

                                     参数:不需要

                                     返回值:返回值类型是SingleTon

                            */

                            publicstatic SingleTon  getInstance(){

 

                                     returns;

                            }

                   }

 

                   //单实例---懒汉式(延迟加载)  有线程安全问题  写线程日志时在提供解决方法

                   classSingleTon

                   {

                            //3.在本类中定义一个本类的对象

                            privatestatic SingleTon s;

 

                            //1.私有化构造

                            privateSingleTon(){}

 

                            //2.提供公共的静态方法可以获得本类对象

                            /*

                                     参数:不需要

                                     返回值:返回值类型是SingleTon

                            */

                            publicstatic SingleTon  getInstance(){

                                     if(s==null){

                                               s=newSingleTon();

                                     }

                                     returns;

                            }

                   }

 

今日帖子练习:

 

ATM操作

         程序运行时

                   提供功能"请选择操作 1.存钱  2.取钱  3.查看  4.退出 5.注册 6.登录

 

分析:

         实体   人   ATM

                      ATM行为:存  取  查看  退出注册 登录

                      人:属性   money

         对于我们当前程序来说,ATM的几个操作无非就是对人的money属性进行操作。

         ATM类要与Person类之间要存在关系。

 

代码实现:

 

import java.util.*; // 导入包

class Test6 {

         publicstatic void main(String[] args) {

                   Scannersc=new Scanner(System.in);

                   //创建一个ATM对象

                   ATMatm=new ATM();

                   while(true){

                            System.out.println("请选择操作 1.存钱  2.取钱  3.查看  4.退出 5.注册 6.登录");

                            inttype=sc.nextInt();//接收键盘输入的信息

                            switch(type){

                                     case1:atm.save();break;

                                     case2:atm.get();break;

                                     case3:atm.search();break;

                                     case4:atm.exit();break;

                                     case5:atm.reg();break;

                                     case6:atm.login();break;

                                     default:System.out.println("无此操作");

                            }

                   }

         }

}


//定义ATM类

class ATM{

         Personp; //做为ATM的一个属性存在。

        

         Scannersc=new Scanner(System.in);

         //存钱

         voidsave(){

 

                   if(p==null){

                            System.out.println("请先注册");

                            return;

                   }                

 

                   if(p.flag){

                            System.out.println("请输入要存入的金额");

                            intmoney=sc.nextInt();

 

                            p.money+=money;

                            System.out.println("存款成功");

                   }else{

                            System.out.println("请先登录");

                   }

         }

                  

         //取

         voidget(){

 

                   if(p==null){

                            System.out.println("请先注册");

                            return;

                   }

                   if(p.flag){

                            System.out.println("请输入要取款的金额");

                            intmoney=sc.nextInt();

                            //判断余额是否充足

                            if(money>p.money){

                                     System.out.println("余额不足");

                                     return;

                            }

                            p.money-=money;

                            System.out.println("取款成功");

                   }else{

                            System.out.println("请先登录");

                   }

         }

 

         //查

         voidsearch(){

                   if(p==null){

                            System.out.println("请先注册");

                            return;

                   }

                  

                   if(p.flag){

                            System.out.println("帐号:"+p.id+"  密码:"+p.password+"  银行余额:"+p.money);

                   }else{

                            System.out.println("请先登录");

                   }

         }

 

         //退出

         voidexit(){

                   System.exit(0);//让jvm停止

         }

 

         //注册对人的id 与password进行赋值

         voidreg(){

 

                   if(p==null){

                            p=newPerson();

 

                            System.out.println("请输入要注册的帐号");

                            p.id=sc.nextInt();

                            System.out.println("请输入要注册的密码");

                            p.password=sc.nextInt();

 

                            System.out.println("注册成功");

                   }else{

                            System.out.println("已经注册");

                   }

         }

 

         //登录的行为

         voidlogin(){

                   //判断是否注册

                   if(p==null){

                            System.out.println("请先注册");

                            return;

                   }

                  

                   System.out.println("请输入帐号");

                   intid=sc.nextInt();

                   System.out.println("请输入密码");

                   intpassword=sc.nextInt();

 

                   if(checkPerson(id,password)){

                            //让这个人是登录状态

                            p.flag=true;

                            System.out.println("登录成功");

                   }else{

                            System.out.println("帐号或密码错误");

                   }

 

         }

 

         /*

                   功能:判断帐号与密码是否正确,如果正确返回true,否则返回false

                   参数: 帐号  密码

                   返回值:正确返回true,否则返回false

         */

         privateboolean checkPerson(int id,int password){

                  

                   returnp.id==id && p.password==password;

         }

}

 

//定义人类

 

class Person{

         intmoney;

         intid;//帐号

         intpassword;//密码

         booleanflag;//它代表人是否登录  true登录  false未登录

}

                   ------- android培训java培训、期待与您交流! ----------