黑马程序员——final 修饰符,抽象类,接口,内部类---

来源:互联网 发布:c语言可视化编程ide 编辑:程序博客网 时间:2024/05/16 18:15


                                   黑马程序员——final 修饰符,抽象类,接口,内部类
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------


final:1.可以修饰变量、类、函数
       2.被final修饰的类不可以被继承(继承弊端:打破封装性),避免子类复写功能。
       3.final修饰的方法是不允许被复写。
       4.被final修饰的变量是一个常量(staic final a)只能赋值一次,即可修饰成员变量也可修饰局部变量。
       
 class Person{
    final int age=23;
     final void showName(){
     
     } 
     void showAge(){
     
     }
  }
class Student extends Person{


      void showName(){  //此时不能使用父类的方法,既不能重写。
      }
        void showAge(){
     
     }
}


抽象类:1.所谓笼统、模糊、,具有相同功能,功能主体不一样,不具体的类。既然是抽象类,里面的方法都是抽象的。使用       abstract关键字定义抽象类
        2.抽象类不能new创建对象,调用抽象方法没有意义。
        3.抽象类的方法要被使用,必须由子类重写父类所有的抽象方法,才建立子类对象进行调用。
        4.抽象类定义抽象方法必须由具体的子类去 实现,如果子类没有实现所有抽象方法,那么子类也是abstract抽象类。
        
abstract Student{
    //final int age=23;
     abstract void study(){  //学生学习方法
     
     } 
  
     void sleep(){
       System.out.print("学生躺着睡觉");
     }
  }
class Pupils extends Student{  //小学生


       void study(){
       System.out.print("小学生朗诵");
     
     } 
 
     
}
class HightStudent extends Student{  //高中生


       abstract void study(){ //重写父类
      System.out.print("高中生背单词");
     } 
  
}


练习 定义;员工类,经理类,技术员类 实现各自的工作,提供方法进行属性访问。
abstract Employe{
    private String  name;
    private String  id;
    private double  pay;
    
    Employe(String name,String id,double pay){
    
          this.name=name;
          this.id=id;
          this.pay=pay;
    
    }
    public bastract void work(){  //员工工作方法必须抽象,员工干活方式不同
     


     
    }


}
class Manager extends Employee{   //经理继承员工这个类属性
     private int bonus; //经理有自己的奖金属性
      Manager(String name,String id,double pay,int bonus){
    
          //this.name=name;
          //this.id=id;
          //his.pay=pay;
          super(name,id,pay); //继承属性
          this.bonus=bonus;
    
    }
       public  void work(){  //员工工作方法必须抽象,员工干活方式不同
     
     System.out.print("经理管理项目工作");
     
    }


}
class Pro extends Employee{   //普通员工继承员工类的属性
     private int bonus;
      Pro(String name,String id,double pay){
    
          //this.name=name;
          //this.id=id;
          //his.pay=pay;
          super(name,id,pay); //继承属性
    
    }
    
     public  void work(){  //员工工作方法必须抽象,员工干活方式不同
     
     System.out.print("普通员工敲代码");
     
    }
 } 
   
 接口(interface):抽象类里面的所有方法都是抽象的,类可以定义一个接口形式表示。
 1.接口的成员默认都是public abstract 类型的  。不可以存在非abstract成员方法。联想(节能灯的 接口,USB接口)
 2.接口是不可以创建具体对象的,因为有抽象方法,要被子类实现,子类对父类抽象方法全部覆盖后才能实例化。
 3.接口中的方法不可以是静态static的
 3.接口之间可以实现多继承,一个接口实现多个接口,多实现。
 4.接口提高功能扩展性,定义一个规则,降低耦合度。


 抽象类与接口的区分:
 1.抽象类在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。多实现
 2.在抽象类中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是抽象的。


 3.抽象类可以包含静态方法,但接口不能用静态方法,所有方法都是抽象的 默认public abstract 
 3.abstract class表示的是你属于我一种"is-a"关系,interface实现关系表示的是"like-a"关系。
 4.实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法(不能声明主体方法,即{ }里面不实现)。
 5.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。
举例:
bastract class Student{
    bastract void study();//抽象学习方法
    
    void sleep(){ //学生都睡觉
      System.out.print("躺着睡觉");
    }
   // void smoke(){  //不是学生都有的基本行为
     // System.out.print("抽烟");
    }
}
interface Smoking{
void smoke(){  //定义接口扩展
}
class zhang extends Student implements Smoking{//继承学生学习方法,扩展自己会抽烟
    void study(){
    }
    public void smoke(){  //张三扩展实现抽烟接口,他会抽烟
}
}
总结:1.扩展功能定义在接口里,基本的定义在体系中(抽象类)
      2.java不直接支持多继承,因为会出现调用的不确定性。
      3. 接口的出现避免Java单继承的局限性,没有方法主体,所以可以继承






 


 模板方法设计模式:定义功能时,一部分功能明确,一部分不确定时,
 确定部分调用不确定部分时就将不确定部分暴漏出去,由这个类的子类去完成,提高复用性。


package com.study;


public abstract GetTime {


/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub


}
 public final void getTime(){ //确定获取时间方法,不能被子类重写
 long start=System.currentTimeMillis();
 
 runcode();
 long end=System.currentTimeMillis();
 System.out.print("毫秒是:"+(end-start));
    
 
 }
 public abstract void runcode();//抽象方法暴漏出去,子类去具体实现


}
class SubTime extends GetTime{


@Override
public void runcode() {
for(int i=0;i<4000;i++){

System.out.print(i);

}

}


}




内部类:1.内部类可以直接访问外部类成员,包括私有成员。内部类中持有一个外部类的引用,格式:外部类名.this
        外部类想访问内部类,必须建立内部对象。


2.外部其他类如何直接访问Static静态内部类的非静态成员
格式:new Outer.Inner().function();
3.内部类定义了静态成员时,该内部类必须是Static静态的。
4.内部类定义在局部时,即局部内部类不可以被成员修饰符修饰,不可以访问所在的局部中的变量,只能访问final修饰的局部变量。
5.方法里定义内部类,内部类前面不能有访问符,可以使用final 或abstract 修饰




class Outer{
    private int a=3;


     class Inner{  //内部类
       int a=4;
      void function(){
      // int a=6;


    System.out.print("Inner:"+Outer.this.a);  //访问外部类变量,打印是3


    }


   }
      void method(){


       Inner in=new Inner();//建立内部对象,访问内部类方法 
             in.function();
    }


}


class InnerClassDemo{


    public static void main(String[] args) {
// Outer out=new Outer();
                   out.method();


           //其他外部类访问内部类中的成员方法
           Outer.Inner in=new Outer().new Inner();
          in.founction();


}








}
匿名内部类:
1.匿名内部类就是内部类的简写,类名称隐去。
2.内部类前提必须继承或实现一个接口
3.匿名内部类就是一个匿名类子类对象,可以理解为带内容的对象
4.内部类中定义的方法最好不超过3个


匿名类使用:当函数的参数是接口类型引用,如果方法不超过3个,可以通过匿名内部类来完成参数传递。
匿名内部类的格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法


------------------异常概念------------------------------
Java异常:是在运行时期发生的不正常情况,用于类的形式对不正常情况进行了描述和封装对象即异常类。
1.两个关键字实现:throws和throw 抛出异常
erro:一般不可处理,由jvm抛出的严重性的问题。
Exception:可以处理的异常。


1.异常抛出:
class Demo{    
    public int method(int[]arr,int index){    
        if(arr==null)    
            throw new NullPointerException("空指针异常,数组的引用不能为空!");    
        if(index >= arr.length)    
            throw new ArrayIndexOutOfBoundsException("数组的角标越界:"+index);    
        if(index<0)    
            throw new ArrayIndexOutOfBoundsException("数组的角标不能为负数:"+index);    
        return arr[index];    
    }    
}    
  
  
class ExceptionDemo{    
    public static void main(String[] args){    
        int[] arr = new int[4]; //数组元素   
        Demo d = new Demo();    
        int num = d.method(arr, 5);   //会报错 
    }    
}  
定义异常类
class FuShuIndexException extends Exception{    //所有异常类基础Exception 父类
    FuShuIndexException(){}    
    FuShuIndexException(String msg){    
        super(msg);    
    }    
}    
  
  
class Demo{    
    public int method(int[] arr,int index)throws FuShuIndexException{ //throws 函数上抛出异常类,可多个  
        if(index<0)    
            throw new FuShuIndexException("角标不能为负数"); //throw 函数体中 抛出异常对象
        return arr[index];    
    }    
}    
  
  
public class ExceptionDemo {    
    public static void main(String[] args) throws FuShuIndexException {    
        int[] arr = new int[3];    
        Demo d = new Demo();    
        int num = d.method(arr, -2);//抛异常    
    }    
}    


编译异常:编译时就被检测异常,一旦出现异常,就使用异常对应的处理方法,编译不通过,是不会运行的。
运行时异常:RuntimeException,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的,或者引发了内部状态的改变导致。
如果在函数抛出该运行时异常,函数可以不声明异常,编译也能通过,调用者使用是停止,让其修改程序(谁用谁处理)。
NullporintException:空指针异常
FuShuIndexException:数组角标越界


2.异常捕捉 try catch
 
这是可以对异常进行针对性处理的方式。
 


具体格式是:
 
try{
 
//需要被检测异常的代码。
 
}
 
catch(异常类  变量){//抛出什么就捕捉什么,内部能解决catch,不能处理就throws 抛出
 
//处理异常的代码。
 
}


class Demo{ 
    public int show(int index){    
        if(index<0)    
            throw new ArrayIndexOutOfBoundsException("角标越界啦");    
        int[] arr = new int[3];    
        return arr[index];    
    }    
}    
class ExceptionDemo{    
    public static void main(String[] args){    
        Demo d = new Demo();    
        try{    
            int num = d.show(-1);    
            System.out.println(num);    
        }    
        catch(ArrayIndexOutOfBoundsException e){ //捕捉到异常,进行处理   
            System.out.println(e.toString());  //打印异常  
            //System.exit(0);退出jvm    
        }    
        finally{//一定会执行的代码。
            System.out.println("finally");    
        }    
        System.out.println("over");    
    }    
}    


3.异常处理的原则: 
a.函数内部如果抛出需要检测到的异常,那么函数上必须要声明(throws)
 否则必须在函数内用try catch捕捉异常进行处理,否则编译失败。


b.如果调用到了声明异常的函数,要么try catch要么throws,否则编译失败。


4.异常注意点:
a.子类在覆盖父类方法时,父类的方法如果抛出异常,那么子类方法只能抛出父类的异常,或者改异常类的子类(父亲有异常,儿子得抛异常)。
b.如果父类抛出多个异常,那么子类只能抛出父类异常的子集,如果父类方法没有抛,子类覆盖上不能抛,只能try捕捉。一句话
老子没有异常抛出,儿子就不能抛(越级了)


5.throws和throw的区别:
1.throws 使用在函数上,throw用在函数内
2.throws抛出的是异常类,可以抛出多个,用逗号隔开。
throw抛出的是异常对象。


单例模式:
Java中23种设计模式:单利模式


单例模式:一个类中只能存在一个对象。方便其他程序访问,提供一些访问方式 。
1.创建构造函数将其有化。
2.在类中创建一个本类对象。
3.提供一个方法获取这个对象。


饱汉模式:
package com.study;


public class Single {


/**
* 单例模式:所谓单例模式,就是一个类中只能实例化一个对象,对外提供访问方式。
* 实现步骤: 1.创建构造函数将其有化。
                      2.在类中创建一个本类对象。
                      3.提供一个方法获取这个对象。
*/
public static void main(String[] args) {

System.out.print("hell,world");

SingleTest a=SingleTest.getInstance();  //类名调用这个单例对象方法




}


}
 class SingleTest{ //类一加载进内存,内存中就已经有了该类的实例对象,
 
private  SingleTest(){ //1.创建构造方法,私有化,内部访问 
 
}
private static SingleTest s=new SingleTest(); //2.创建本类对象,外部类名访问,只能静态方法,使用类名进行静态方法调用

public static SingleTest getInstance(){  //提供访问获取单例对象的方法

return s;
}


 
 }


懒汉模式:


class  Single
{        
        private single(){}
        private static Single s =null;
        public void single getInstance()
        {
                if(s==null)  //判断线程s==null 线程中还没有实例,继续往下走
                {
                        synchronized(single.class) //一个线程进入后上锁
                        {
                                if(s==null)// 
                
                                s =new single();//实例对象
                        }
                }
                return s
        
        }
        
}


---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! -------------------------------


0 0