zoukankan      html  css  js  c++  java
  • JavaSE | 接口| 枚举| 注释| 异常

    包:

    1、包的作用:
    (1)避免类的同名(区分类);类的全名称:包.类名

    回忆:java.util.Scanner
    java.util.Arrays
    java.lang.String
    j
    (2)可以限定某些类或成员的可见范围;(权限)
    如果某个类或成员省略了权限修饰符,它的可见范围是本包

    (3)用于组织管理项目中众多的类

    2、包的声明的格式:package 包名;

    声明的要求:
    (1)这句package语句必须在“源文件”代码的首行
    (2)包名:A:所有单词都小写,每一个单词之间使用.分割;  B:一般习惯上用公司的域名倒置加模块名 com.atguigu.xxx;

    3、
    编译:javac 源文件名.java;       ----->>>   编译:javac -d . 源文件名.java
    运行:java 类名                           ----->>>   运行:java 包.类名

    -d:directory文件夹,目录; .:表示当前目录

    4、如何使用其他的包?  前提:被使用的类必须是可见的
    (1)使用类的全名称
    (2)使用import语句先导包,然后使用类的简名称;   import 包.类名;

      特殊情况:要使用的两个类同名,包名不一样;那就一个导包用简名称,一个使用全名称

    * 导包:
    * (1)import 包.类名;
    * (2)import 包.*;
    * (3)import static 包.类名.静态成员;
    * (4)import static 包.类名.*;

    * (3)(4)就是静态导入,JDK1.5之后引入

    * JDK1.5增加的:
    * (1)foreach
    * (2)枚举
    * (3)注解
    * (4)可变参数
    * (5)静态导入


    * JDK1.8增加的:
    * (1)接口的默认方法和静态方法

     final关键字

    * 关键字:final,最终的
     * 它也是一个修饰符
     * 
     * 1、它可以修饰什么?
     * final可以修饰:类(包括外部类和内部类)、变量(包括局部变量、实例变量和类变量)、方法(静态方法和非静态方法); final不能用于修饰构造方法
     * 
     * 2、它修饰后有什么不同?
     * (1)修饰类,即class前面出现了final
     * 表示这个类是最终类,即这个类不能被继承了,没有子类,它是太监类,没有子孙后代
     * 例如:String类
     * 
     * (2)修饰方法,即返回值类型前面出现final
     * 表示这个方法是最终实现版本,即这个方法不能被重写
     * 
     * (3)修饰变量,即在变量数据类型前面出现final;  被final修饰的变量只能在变量定义时初始化。
     * 表示这个变量的值不能被修改,它是常量,一般要求常量名大写,每个单词之间使用_,常量必须赋值
     * 
     * 例如:Math.PI

    native关键字

    * 关键字:native
     * 它也是修饰符
     * 
     * 1、native可以修饰什么?
     * 可以修饰方法
     * 
     * 2、native修饰的方法是什么意思?
     * 表示这个方法是一个“原生”的方法,即它的方法体的实现不是用Java语言实现的,是有C/C++等语言实现的,
     * 实现后编译为.dll文件,然后由Java代码调用。
     * 
     * 对应调用者,使用者来说,可以把它当成Java实现的方法一样使用。
     * 而且子类可以选择用Java代码重写native方法
     */
    public class TestNative {
        public static void main(String[] args) {
            Object obj = new Object();
            int hashCode = obj.hashCode();
            System.out.println(hashCode);
        }
    }
    class Student{
        private int id;
        private String name;
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + id;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Student other = (Student) obj;
            if (id != other.id)
                return false;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }
        
    }
    View Code

     接口

    * 1、声明一个接口
     * 【修饰符】 interface 接口名{
            }    //类似于类的声明(class)
    可以用来修饰interface的有public, static也对; private和protected都不对;接口的内部成员都是public
     * 2、接口的成员
     * JDK1.8之前:
     *       (1)全局静态的常量  public static final  如 int MAX_SPEED = 20000;
     *       (2)公共的抽象的方法  public abstract   如:void run();
     * JDK1.8之后:增加了两个成员
     *      (1)默认方法
     *      (2)静态方法  
     * 
     * 3、如何使用接口?
     * (1)全局静态的常量:通过接口名直接调用
     * (2)抽象方法,由实现类(就是子类)来实现它;;;“子类“要实现接口重写接口的方法,不一定要继承父类。
     * 
     * 【修饰符】 class 实现类名  implements 接口们{
     *         //如果这个类不是抽象类,那么必须实现接口的所有的抽象方法
     * }
     * 
     * 接口可以比喻成“干爹”,可以有好几个
     * 继承可以比喻成“亲爹”,只能有一个,所以单继承
     * 
     * 4、接口的特点
     * (1)接口也是不能直接创建对象
     * (2一个类可以同时实现多个接口
     * (3一个类可以同时继承它的父类,又实现接口,要求必须继承在前,实现在后
     * 【修饰符】 class 实现类名 extends 父类  implements 接口们{
     *         //如果这个类不是抽象类,那么必须实现接口的所有的抽象方法
     * }
     * (4)接口和父类有点像,所以接口的变量与实现类对象可以构成多态引用
     * (5)一个实现类实现接口时,必须实现接口的所有的抽象方法,否则这个实现类也得是抽象类
     * (6接口可以继承接口,并且可以继承多个接口。
     * 【修饰符】interface 接口名 extends 接口们{
     * }
     * 
     * 关系:
     * 类与类之间:继承,单继承  extends
     * 类与接口之间:类实现接口,可以多实现 implements
     * 接口与接口之间:继承,多继承 extends
     * 
    for(int i = 1; i < arr.length; i++){
                for(int j = 0; j < arr.length - i; j++){
            /*
             * 假设传入的是Student[]数组,里面都是学生对象
             * 如何表示前面的学生对象arr[j]比arr[j+1]大
             */
            //需要调用arr[j]的compare方法,怎么才能调用compary方法呢,
            //参数为Object类型向下转型为Student类型,它重写了compary方法
            //通过arr[j].compare(arr[j+1])>0,就可以确定arr[j]比较arr[j+1]大    
                    Sortable left = (Sortable) arr[j];//这一步很关键啊
                    if(left.compare(arr[j + 1]) > 0){   //if(arr[j] > arr[j+1]){
                        //交换两个元素,temp和元素的类型一样就可以
                        
                        Object temp = arr[j];
                        arr[j] = arr[j+1];
                        arr[j+1] = temp;
                    }
                }
            }
            
        }
    * JDK1.8之后,接口增加了两个成员:
     * 1静态方法
     *     和类中的静态方法的格式一样。
     *     调用时:通过“接口名."调用即可
     * 
     * 原来的核心类库中,有Collection接口和Collections工具类(全部是静态方法),
     *                 Path接口和Paths工具类(全部是静态方法)
     *             后面的工具类是为前面的接口服务的。
     *         原来为了为某个接口提供工具类,还要增加一个类,现在就不同了,直接在接口中声明静态方法即可。
     *         而且这些静态的实现和接口的实现类是什么类型无关。
     * 
     * 2默认方法
     *     语法格式:
     * 【修饰符】 interface 接口{
     *         【修饰符】 default 返回值类型  方法名([形参列表]){
     *             方法体
     *         }
     * }
     * 
     *     如何调用?
     *     必须通过接口的"实现类对象."才能调用
     * 
     *     某一个接口的某个抽象方法,可能它的多数实现类对该方法的实现是一样的,那么就没必要每一个实现类都写一遍。
     *  把这样的方法实现,提取到接口中声明为默认方法,如果其他不一样的实现类,可以选择“重写”。
     */
    public class TestInterface {
        public static void main(String[] args) {
            MyInter.test();  //接口中的静态方法直接    接口名.静态方法;
            
            MyImp myimp = new MyImp();
            myimp.fun();//通过接口的实现类对象来调用 接口的default默认方法;
            
            myimp.method();//通过接口的实现类对象来调用 接口的default默认方法;
            
        }
        
    }
    
    interface MyInter{
        public static void test(){
            System.out.println("接口中的静态方法直接接口名.来调用哦");
        } 
        public default void fun(){
            System.out.println("接口中的默认方法fun通过接口的实现类创建对象来调用");
        }
        public default void method(){
            System.out.println("接口中默认方法method通过接口的实现类创建对象来调用");
        }
        
    }
    
    class MyImp implements MyInter{
    
        /*@Override   //接口中的方法不是抽象方法,可以不用重写;
        public void fun() { 
            // TODO Auto-generated method stub
            MyInter.super.fun();   
        }
        
        */
        
    }
    View Code

    /*
    * 默认方法的冲突问题:
    * 1、当某个类实现了多个接口,多个接口的默认方法的方法签名是一样的
    * 必须重写,但是在重写的时候可以选择(1)保留其中一个(2)选择完全重写
    *
    * 2、当某个类继承了父类,又实现了接口,但是父类中有一个方法和接口中的默认方法的方法签名是一样的
    * 默认选择保留“父类”,即子类创建对象默认调用的是父类中的方法,如果子类重写了父类的方法就按照子类重写的方法;

    当然也可以重写接口中的方法,就会调用接口中的方法,如 InterD.super.test( ) ;

    当然也可以选择重写(1)选择父接口的(2)完全重写 
    */

    public class TestDefaultMethod {
    
        public static void main(String[] args) {
            
            Sub s = new Sub();
            s.test();
            
            
            Son son = new Son();
            son.test(); //如果子类没有重写,就默认调用父类的
            
        }
        
    }
    
    interface InterA{
        public default void test(){
            System.out.println("我是接口A的默认方法test");
            
        }
    }
    
    interface InterB{
        public default void test(){
            System.out.println("我是接口B的默认方法test");
        }
    }
    
    class Father{
        
    }
    
    class Sub extends Father implements InterA, InterB{
    
        
        @Override
        public void test() {
            // TODO Auto-generated method stub
            InterA.super.test();//保留A接口的默认实现
            InterB.super.test();//保留A接口的默认实现,也可以实现两个都保留;也可以进行重写;
            System.out.println("我重写,两个都不要了");
        }
    
    }
    
    
    interface InterD{
        public default void test(){
            System.out.println("我是接口D中的默认方法test");
        }
    }
    
    class Fu{
        public void test(){
            System.out.println("我是父类Fu中的方法test");
        }
    }
    
    class Son extends Fu implements InterD{
        public void test(){
            InterD.super.test(); //重写接口D中的方法;  子类重写父类的方法了,就不会调用父类的方法了调它自己的
            System.out.println("我是子类Son中的方法test,重写了父类的了");
            
            
        }
        
        
    }
    View Code

     用实现类代替接口

    public class TestInterface {
    
        public static void main(String[] args) {
            //AA aa = new BB(); //需要一个接口,给个实现类即可
            AA aa = new CC(); //多态的传递
            // AA aa = new BB(); BB bb = new CC(); 构建CC,等同于构建他的父类,父类可以代替接口实现;能代替不代表实现了接口,class CC extends BB implements AA这样子就实现了接口
            //System.out.println(aa);
            System.out.println(CC.class.getInterfaces().length); //CC并没有实现接口AA
        }
    }
    interface AA{
    
    }
    class BB implements AA{
    
    }
    class CC extends BB{
    
    }

    简单工厂模式

    * 简单工厂模式(了解):
    * (1)当创建某个对象比较麻烦
    * (2)想要与被创建的对象的类型解耦合
    *
    * 工厂模式的目的:对象的创建者与对象的使用者角色分离
    *
    * 代码的结构:
    * (1)接口
    * (2)有接口的很多实现类
    * (3)有一个工厂类,专门new接口的各种实现类的对象
    * (4)使用接口的实现类对象的地方,通过工厂类之间获取对象,而不直接new实现类对象
    *
    * 耦合:依赖,关联
    */

    public class TestFactory {
    
        public static void main(String[] args) {
            String str = new String();  //TestFactory与String类发生耦合,依赖
            //对象的使用者TestFactory
            //想要获取宝马车的对象; new出BMW对象,接口类型Car b 
            Car c = new BMW();//与BMW发生耦合,对象的使用者和创建者都是TestFactory
            c.run();
            
            
            //对象的使用者TestFactory不负责BMW和Aodi对象的创建,与BMW和Aodi类解耦合
            Car b = Factory.getCar("宝马");
            b.run();
            Car a = Factory.getCar("奥迪");
            a.run();
        }
    
    }
    
    class Father{
        
    }
    
    class Son extends Father{
    
    }
    
    interface Car{
        void run();
    }
    class BMW implements Car{
    
        @Override
        public void run() {
            System.out.println("宝马来了。。。");
        }
    }
    
    class AoDi implements Car{
    
        @Override
        public void run() {
            System.out.println("奥迪来了。。。");
            
        }
    }
    class Factory{
        //工厂只负责创建对象;创建一个getCar方法来生产Car的对象
        public static Car getCar(String type){
            if("宝马".equals(type)){
                return new BMW();
            }else if("奥迪".equals(type)){
                return new AoDi();
            }
            return null;
            
        }
    }
    View Code

    代理模式

    * 代理:代购、中介
    * 把麻烦,多变交给代理,核心的不易变化的还是自己来做。
    *
    * 静态代理和动态代理。
    *
    * 代理模式:(了解)
    * 1、接口:主题接口
    * 2、被代理者
    * 3、代理者
    * (1)被代理者和代理者都要实现主题接口。
    * (2)要指定代理者为谁代理,即代理者中必须持有被代理者对象的引用
    *
    * 静态代理:

    public class TestProxy {
    
        public static void main(String[] args) {
            
            DaiGou d = new DaiGou(new Customer()); //用有参构造器,创建DaiGou的对象d,并给他赋值初始化
            d.buy();    //构造器中的形参Subject target, 把实参new出Customer对象传给它;最后由d对象来调用方法
            
        }
    
    }
    
    interface Subject{
        void buy();  //抽象方法省略了public abstract 
    }
    
    //被代理者  --Customer类实现了Subject接口;
    class Customer implements Subject{
    
        @Override
        public void buy() {
            // 最核心的自己写
            System.out.println("一手交钱一首交货");
        }
        
    }
    
    class DaiGou implements Subject{
    
        private Subject target;  //类DaiGou的属性,接口类型的引用数据类型targer; 被代理者对象的引用
    
        public DaiGou(Subject target) {  
            super();
            this.target = target;  //在构造器中给属性targer初始化
        }
    
        @Override
        public void buy() {
            System.out.println("筛选商品");
            
            target.buy();   //一手交钱一首交货
            System.out.println("反馈下");
            
        }
        
    }
    View Code

    枚举

    * 枚举:也是一个种类型,也是一个类
    * 1、什么是枚举?
    * 中文:枚举 的近义词 列举,穷举,罗列
    * Java中,枚举,罗列出该类型的所有对象
    *
    * 2、什么情况会用枚举?
    * 当某个类型它的对象是有限的几个,这个时候就可以使用枚举。
    * 3、如何声明枚举类
    * JDK1.5之前
    * JDK1.5之后

    public class TestEnum {
        public static void main(String[] args) {
    //        Season s = new Season();//构造器不可见
            
            //如何获取春天对象
            Season spring = Season.SPRING;  类型 类名 = 类型.静态对象
            System.out.println(spring);
            
            Season summer = Season.SUMMER;
            System.out.println(summer);
        }
    }
    //JDK1.5之前
    /*
     * (1)限定使用者创建对象;    2)把有限的几个对象,提前创建好,并存起来,大家共享
     * 存对象:肯定用变量才能存;   共享:类变量,静态变量;      随处可用:public 
     */
    class Season{
        //(2)把有限的几个对象,提前创建好,并存起来,大家共享
        public static final Season SPRING = new Season();
        public static final Season SUMMER = new Season();
        public static final Season FALL = new Season();
        public static final Season WINTER = new Season();
        
        //(1)限定使用者创建对象,把构造器私有化
        private Season(){
            
        }
        //可以定义其他的成员
        public String toString(){
            if(this == SPRING){
                return "春眠不觉晓,处处闻啼鸟。";
            }else if(this == SUMMER){
                return "小荷才露尖尖角,早有蜻蜓立上头";
            }else if(this == FALL){
                return "停车坐爱枫林晚,霜叶红于二月花。";
            }else{
                return "千山鸟飞绝,万径人踪灭。";
            }
        }
    }
    * JDK1.5之后:
     * 1、枚举类的声明格式
     * 【修饰符】 enum 枚举类名{
     *       枚举类的常量对象列表 【;
     *         其他成员列表
     ** }
     * 
     * 说明:
     * (1)如果枚举常量对象列表后面要写其他成员,那么需要在常量对象列表后面加;分隔,如果没有其他成员,那么;可写可不写
     * (2)构造器一定是私有化的
     * (3)枚举类型的默认父类不是Object,而是java.lang.Enum类,当然Enum也是Object的子类
     * 枚举类型不能再继承别的类型
     * 
     * java.lang.Enum类:
     * (1)构造器
     * protected Enum(String name,int ordinal)
     * name是为Enum类中的name属性赋值,自动赋值为常量对象的名称
     * ordinal是Enum类中的ordinal属性赋值,自动赋值为常量对象的“序号”,这个序号是从0开始
     * 
     * 他们的get方法没有按照普通类的get方法的命名,而是直接用属性名作为get方法的名称:name(),ordinal()
     * 
     * 因为父类Enum只有唯一的一个有参构造,意味着我们自己写的枚举类的构造器和普通类(默认调用父类的无参构造)不一样,
     * 默认调用的是父类的有参构造。
     * 
     * (2)Enum实现了java.lang.Comparable接口
     * 所有的枚举类型都支持比较大小,因为Enum实现了java.lang.Comparable接口,按照常量对象的顺序比较大小。
     * 父类中把这个int compareTo()加了final,子类不能重写
     * 
     * (3)两个API中没有的方法
     * static 枚举类型[] values():用来返回枚举类型的所有常量对象
     * static 枚举类型  valueOf(字符串类型的常量对象名) -->> 枚举类名.valueof(“ ”)
         Week sunday = Week.SUNDAY;
            System.out.println(sunday); //对象sunday打印的是 toString的内容;
            System.out.println(sunday.name());
            System.out.println(sunday.ordinal());
            
            System.out.println("----------------");
            
            Week[] values = Week.values();
            for (Week week : values) {
                System.out.println(week);
            }
            
            Week w = Week.valueOf("MONDAY");
            System.out.println(w);
            

    System.out.println(Week.valueOf("SUNDAY")); --->> 星期天       //(SUNDAY("星期天"); )

    public enum Status {
    
        BUSY("忙得热火朝天,无法再安排其他任务"), //创建的对象时候用的是有参构造;
        FREE(),   //用的是无参,默认null
        VOCATION(), 
        LEFT("离职了");
        
        private String desc;
    
        private Status() {
        }
    
        private Status(String desc) {
            this.desc = desc;
            
        }
    
    
    
                    Status busy = Status.BUSY;
            
            
            Employee[] emp = new Employee[5];
            emp[0] = new Employee("kris", 10000, Status.BUSY);//busy
            
    for (Employee employee : emp) {
                System.out.println(employee.toString());//employee  <==> employee.toString();
            }
                   

     注释

    注解(annotation):它又称为注释,它本质上也是注释,只不过它是代码级别的注释,即它用代码注释代码。
    * 因为说注释容易让人误解为单行和多行的普通注释,很多人就故意叫做“注解”
    * 注解是JDK1.5之后引入。
    *
    * 普通的注释:用文字去注释代码
    * (1)单行注释
    * (2)多行注释
    *
    * 文档注释:用代码和文字一起去注释代码。
    *
    * 注解长什么样? @注解

    * 一个完整的注解,它应该有三部分组成:
    * (1)定义,声明
    * 可能是程序员自己声明的,也可能是别人声明好的;* 开发中,绝大多数都是用别人声明好的。

    * (2)注解的使用
    * 你看到在类上面、方法上面、属性上面....用到了@注解,就是在使用注解
    * (3)读取注解
    * 得有代码去读取这个注解,理解代码的用意,信息...
    * 读取注解需要用代码去读取,这个代码我们称为“注解处理流程”,大多数情况下,这个代码也是别人写好的,
    * 一般都是谁定义,谁复制编写读取注解的代码。
    *
    * 注解在后面的框架中使用最多,它的作用是用来替代xml的配置文件,对代码进行解释。
    * 因为xml的配置方式,一个是复杂,另一个与所解释的代码是独立的,所以有的地方不用xml,用注解

    常见的注解

    * 常见的注解:
     * 
     * 一、系统定义的最基本的三个注解(必须都认识,会写,会用)
     * 1、@Override:
     * 这个注解的声明是在JDK的核心类库中声明的,
     * 这个注解的读取是编译器来读取的,编译器:javac.exe,eclipse中有自己编译器
     * 这个注解的使用由程序员来使用,用在所有的重写的方法的上面,表示让编译器,按照重写的要求对该方法进行格式检查和编译。
     * 
     * 重写的要求:
     * (1)方法名和形参列表必须相同
     * (2)返回值类型
     *         如果是基本数据类型和void,必须相同
     *         如果是引用数据类型,必须<=   子类重写的方法的返回值类型<=父类被重写的方法的返回值类型
     * (3)权限修饰符:必须>=            子类重写的方法的权限修饰符的可见范围>=父类被重写的方法的权限修饰符的可见范围
     * (4)抛出的异常列表类型范围:?
     * (5)其他修饰符:被重写的方法不能是static,private,final
     * 
     * 2、@SuppressWarings(xx)    
     * 这个注解的声明是在JDK的核心类库中声明的,
     * 这个注解的读取是编译器来读取的,编译器:javac.exe,eclipse中有自己编译器
     * 这个注解的使用由程序员来使用,用在任意需要抑制警告的地方    
     * 
     * @SuppressWarnings("all")
     * @SuppressWarnings({ "rawtypes", "unused" })
     * 
     * 3、@Deprecated 
     * 这个注解的声明是在JDK的核心类库中声明的,
     * 这个注解的读取是编译器来读取的,编译器:javac.exe,eclipse中有自己编译器
     * 这个注解的使用由程序员来使用,用在任意需要标记为“已过时”的元素上面,可能是方法,可能是类,
     * “已过时”的东西,不建议程序继续使用的,如果使用可能有问题
     * 
     * 删除的行为一定要谨慎。
     * 
     * 编译器如果遇到了程序员使用了已标记为“已过时”的元素时,它会弹出警告

     文档注解,文档注释

    二、文档注解,文档注释
     * 文档注解的声明,也有JDK核心类库声明过了; * 读取:javadoc.exe来读取
     * @author:表示作者
     * @version:表示版本
     * @since:起始版本
     * @see:另请参考
     * @param:形参
     * @return:返回值
     * @throws:抛出的异常列表
     * 
     * @param、@return、@throws只能在方法上使用
     * @param 形参名 形参的数据类型  形参的解释
     * @return 返回值类型  说明
     * @throws 异常类型 说明
    import javax.management.RuntimeErrorException;
    
    /**
     * @author Administrator
     * @version 1.8
     * @since 1.0
     * @see java.lang.Object
     * @see java.lang.Math
     */
    
    public class TestAnnotation {
    
        public static void main(String[] args) {
            /**java程序主入口
             * @param args String[] 命令行参数
             */
            @SuppressWarnings(value = { "unused" })
            int a = 10;
        }
        
        public static int getMax(int a, int b){
            /**
             * 从两个整数中找出最大值
             * @param a int
             * @param b int
             * @return int 返回最大值
             */
            
            return a > b ? a :b;
        }
        
        public static int divide(int a, int b) throws RuntimeErrorException{
            
            /**
             * 这是一个求两个整数的商
             * @param int a 
             * @param int b
             * @return int 
             * @throws RuntimeException,当b为0时抛出异常
             */
            
            if(b == 0){
                throw new RuntimeException("除数不能为0");
            }
            return a/b;
        }
        
        @Deprecated
        public void print(){
            System.out.println("过时的方法啊");
        }
    
        @Override
        public String toString() {
            return "TestAnnotation [toString()=" + super.toString() + "]";
        }
        
    }
    View Code

    单元测试

    * JUnit框架不是JRE核心类库,需要单独引入它的jar,类库;  eclipse等IDE(集成开发工具)都直接集成了JUnit框架
     * 
     * 三、单元测试
     * 声明和定义:JUnit框架中定义的* 读取:由java + JUnit框架读取
     * 
     * 如何运行?
     * 如果没有选择,那么当前源文件中的所有的单元测试都会运行
     * 如果选中某个方法,只运行某一个;
     * 
     * @Test:   要先引入import org.junit.Test;
     *加在需要单独测试的方法。* 
     * @Before  导入 import org.junit.Before;  与之类似的 --->>> @After 是在@Test方法后边最后才执行。
     * 加在需要在单元测试方法前面运行的方法上;  如public void test(){ }; *执行的特点:每一个@Test方法前面都会执行这个方法,再执行@Before; 
     * 
     * @BeforeClass            @BeforeClass
     * 加在需要在类初始化时执行的方法上。 如public static void test(){  }; 最先执行,首行位置;* 
     * @AfterClass    类似上边@BeforeClass的用法
     *     加在需要在类所有的测试方法之后执行的方法上
     *     
    这四个都有要求:方法所在的类必须是public
    * 方法本身必须是public,而且是无参无返回值的,静态的
    @Test
        public void test(){
            System.out.println("Hello");
        }
        @Before
        public void test1(){
            System.out.println("hi");
        }
        @After
        public void test2(){
            System.out.println("Test之后");
        }
        @BeforeClass
        public static void test3(){
            System.out.println("嘿嘿");
        }
        @AfterClass
        public static void test4(){
            System.out.println("嘿哈");
        }
    View Code

    自定义注释

    * 枚举看成是类
     * 注解看成是接口
     * 
     * 注解:
     * (1)声明
     * (2)使用
     * (3)读取
     * 
     * 一、自定义注解
     * 1、语法格式:
     * 【修饰符】 @interface 注解名{
     * }
     * 
     * 2、加元注解说明一下
     * 元注解:注解注解的注解,给注解加的注解。它们在java.lang.annotation包* (1)@Target 
     * @Target(ElementType.xx)
     * @Target({ElementType.xx,ElementType.xx,...})
     * ElementType是一个枚举类型,有很多常量对象:例如:TYPE,METHOD(方法),FIELD(属性),CONSTRUCTOR....
     *     TYPE(包含 Class, interface (including annotation type), or enum declaration )
     * @Target作用:限制自定义的注解的使用的目标位置
     * 
     * (2)@Retention
     * @Retention(RetentionPolicy.SOURCE):源代码阶段   该注解只能被编译器读取
     * @Retention(RetentionPolicy.CLASS):字节码阶段  该注解只能被编译器和类加载器* @Retention(RetentionPolicy.RUNTIME):运行时阶段  该注解可以在运行时仍然被读取
     * 
     * SOURCE < CLASS < RUNTIME
     * 
     * @Retention的作用:限制自定义注解的寿命,可以“滞留”到什么阶段
     * RetentionPolicy也是枚举类型,常量对象只有三个:SOURCE,CLASS,RUNTIME
     * 
     * (3)@Documented
     * 标记某个注解是否可以被javadoc读取到API中。
     * 
     * (4)@Inherited
     * 标记某个注解是否可以被子类继承
     * 
     */
    package com.atguigu.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    public class TestDefineAnnotation {
    
        public static void main(String[] args) {
            
            //读取MyClass类上面的注解,用到了反射
            Class clazz = MyClass.class;
            MyAnnotation my = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
            System.out.println(my);
            
            Class clazz2 = MySub.class;
            MyAnnotation my2 = (MyAnnotation) clazz2.getAnnotation(MyAnnotation.class);
            System.out.println(my2);
    
        }
    
    }
    
    //@YoursAnnotation
    class MyClass{
        //@YoursAnnotation  //不能在属性上使用,因为它规定了只能使用在METHOD即方法上
        @MyAnnotation
        private String filed;
        
        @MyAnnotation
        @YoursAnnotation
        public void test(){
            
        }
        
    }
    
    class MySub extends MyClass{
        
    }
    
    @Inherited  //标记这个注解可以被子类继承;
    @Retention(RetentionPolicy.RUNTIME) //可以在运行时阶段读取;
    @interface MyAnnotation{  //自定义一个注解;
        
    
    }
    @Documented
    @Target(ElementType.METHOD) //限制自定义注解使用的目标位置
    @Retention(RetentionPolicy.SOURCE) //只能被编译器读取;
    @interface YoursAnnotation{
        
    }
    View Code
    * 自定义注解
     * 
     * 1、语法格式:
     * @元注解
     * 【修饰符】 @interface 注解名{
     * }
     * 
     * 
     * @元注解
     * 【修饰符】 @interface 注解名{
     *         配置参数
     * }
     * 
     * 没有配置参数的注解:
     * (1)@Override
     * (2)@Deprecated
     * (3)@Documented
     * (4)@Inherited
     * (5)@Test
     * 
     * 有配置参数的
     * (1)@SuppressWarnings(xx)
     * (2)@Target(xx)
     * (3)@Retention(xx)
     * (4)@WebServlet(xx)
     * 
     * 1、配置参数的声明
     * (1)声明格式:
     *     数据类型  参数名();
     * (2)配置参数在声明时,可以有默认值
     *     数据类型  参数名() default 默认值; 如 String info() default "atguigu";
     * (3)数据类型
     * 注解的配置参数的数据类型的要求:8种基本数据类型,4种引用数据类型(String,Class,枚举,注解*                             可以是它们的数组类型,例如:int[],String[],枚举类型[]等
     * 
     * 2、如果有配置参数,在使用时
     *(1) @注解名(参数名1 = 参数值1,参数名2 = 参数值2,。。。。)
     *(2)如果这个注解只有一个配置参数,并且它的名字叫做value,那么可以省略value=
     *
     *换句话说,声明配置参数时,参数名首先考虑value
     * 
     * 3、读取配置参数值时,   变量 = 注解对象.参数名()
     * 
     * 
     * 回忆:default
     * (1)switch
     * (2)接口
     * (3)注解配置参数的默认值
     * 
     * 数据类型:
     * (1)数据类型有哪些:
     * (2)变量的数据类型: 都可以
     * (3)属性的数据类型什么要求: 都可以
     * (4)形参的数据类型什么要求: 都可以
     * (5)返回值类型的类型有什么要求: 都可以
     * (6)switch(表达式)中表达式的类型要求:4种基本数据类型,2种引用数据类
     * (7)注解的配置参数的数据类型的要求:8种基本数据类型,4种引用数据类型(String,Class,枚举,注解)
     *                             可以是它们的数组类型,例如:int[],String[],枚举类型[]等
     */
    public class TestAnnotation2 {
        public static void main(String[] args) {
            @SuppressWarnings("rawtypes")
            Class clazz = TestA.class;
            AnnotationA my = (AnnotationA) clazz.getAnnotation(AnnotationA.class);
            System.out.println(my);
            
            String str = my.info(); //对象.方法 来进行调用;
            System.out.println(str);
        }
    
    }
    @AnnotationA(info = "atguigu", age = 22, value = 88.9) //赋值时像属性,变量
    class TestA{                              //只有一个参数时可以省略value = 
        
    }
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @interface AnnotationA{
        String info() default "尚硅谷"; //可以有默认值
        int age();  //配置参数的声明;
        char gender() default '男';
        double value();
        
    }

    异常

    * 所谓异常:程序大多数情况下是可以正常,正确的运行,但是有的时候因为一些不可控的因素,导致程序运行异常,中断。
    * 例如:复制文件时,因为目标盘空间不足; 聊天功能时,因为网络中断;* 计算两个数的商,用户输入的除数为0

    1)语法错误;   2)逻辑错误  --->>  它们不是异常。。。

    异常的作用:使得系统可以通过捕获异常对象,然后处理异常,使得程序继续运行,否则,如果一旦异常,程序就会挂了。使得程序更健壮。

    * Java中是如何处理异常?(原理)

    * 当某句代码发生异常时,程序会在这句代码“停”下来(下面的代码是无法执行的)
    然后JVM(大多数是JVM,有的时候也可能是程序中自己new)
    会创建一个“合适类型的异常的对象”,并且“抛”出来;
    JVM会在该句代码的“外围”搜索是否有"try..catch"可以“捕获”这个异常,如果可以“捕获”那么程序从"try..catch"下面继续运行,
    如果没有找对应的"try..catch",或者先有的"try..catch"无法“捕获”,
    那么程序会把这个异常对象“抛”给“上级”如果上级可以“捕获”,那么就“上级”的"try..catch"下面继续运行,
    否则接着往上抛,一直到main,如果main也“捕获”不了,就挂了。

    异常的类型

    * 异常的类型:
     * java.lang.Throwable:Throwable 类是 Java 语言中所有错误或异常的超类。
     * (1)只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。
     * (2)只有此类或其子类之一才可以是 catch 子句中的参数类型。 
     * 
     * “抛”:JVM抛,throw抛
     * “抓,捕获”:catch
     * 
     * 两个子类的实例,Error 和 Exception,通常用于指示发生了异常情况。
     * 通常,这些实例是在异常情况的上下文中新近创建的,因此包含了相关的信息(比如堆栈跟踪数据)。 
     * 
     * 分为:
     * Error:错误,严重的异常,用于指示合理的应用程序不应该试图捕获(catch)的严重问题。
     *         例如:VirtualMachineError的两个子类: OutOfMemoryError, StackOverflowError
     * Exception:异常
     *         非受检异常/运行时异常:RuntimeException及其它的子类
     *         受检异常/编译时异常:除了运行时异常,剩下的都是编译时异常
     * 
     * 编译器在检查程序时,遇到你throw或throws出RuntimeException,编译器不会强制要求你编写try..catch或继续throws处理;
     * 编译器在检查程序时,遇到你throw或throws出非运行时异常,那么编译器会强制要求你编写try...catch或继续throws否则编译不通过。
     *

      Throwable是所有错误和异常的父类,超类。

      Exception是所有异常的父类,它分为RuntimeException和非RuntimeException。

    try..catch..finally形式有三种:1) try..catch;  2) try...catch..finally;  3) try..finally

    try...catch 

    * try...catch
     * 1、语法格式:
     * try{
     * 
     *         可能发生异常的语句块;
     * 
     * }catch(异常类型1  异常名){
     *         处理该异常的代码;
     * }catch(异常类型2  异常名){     //catch -->> catch --> 一定是有先后顺序的,从子类---->>>父类,高级的
     *         处理该异常的代码;
     * }catch(异常类型3  异常名){
     *         处理该异常的代码;
     * }
     * ....
     * 
     * try..catch的执行过程:
     * (1)如果try中的代码没有异常,那么try中的代码执行完,正常执行try..catch下面的代码
     * (2)如果try中的代码发生异常,首先,try中发生异常那句代码  后面的代码是无法执行,其次,在try中抛出一个
     * 异常对象,catch会按从上到下,依次尝试“捕获”,如果有一个“捕获”了,下面的catch就不看。
     * 所有要求子异常类型写上面,父异常类型写下面。
     * (3)如果try中的代码发生异常,并且所有的catch都没有“捕获”,那么try..catch下面的代码就无法执行了,
     * 会把异常对象抛出“上级——调用者”,如果已经是最上级(main),就挂了。
     * 
     * 这个特点有的像:
     * if...else if....
     * 
     * 
     * 
     * 提示:把字符串类型的数字转成int的值
     * Integer.parseInt(字符串)

    try...catch...finally 

    * try...catch...finally
     * 2、语法格式:
     * try{
     * 
     *         可能发生异常的语句块;
     * 
     * }catch(异常类型1  异常名){
     *         处理该异常的代码;
     * }catch(异常类型2  异常名){
     *         处理该异常的代码;
     * }catch(异常类型3  异常名){
     *         处理该异常的代码;
     * }finally{
     *         无论try中是否发生异常,也不管catch是否能够捕获异常,finally中一定要执行。
     * }
     * 
     * finally块中一般编写:释放资源,断开连接等代码。
     * 
     * 
     * 面试题:final,finally,finalize的区别?
     * final是修饰符,修饰类,表示不能被继承,修饰方法,表示不能被重写,修饰变量,表示值不能被修改是常量。
     * finally:是try..catch..finally的一部分,无论try中是否发生异常,也不管catch是否能够捕获异常,finally中一定要执行
     * finalize:是一个方法名,在Object类中,表示当对象被“垃圾回收器GC”回收之前调用,有它在就不回收了,只有第一次有效,第二次无效会被gc回收。
    
     * 形式:
     * try..catch
     * try..finally
     * try..catch...finally
    public static void main(String[] args) {    
            int num3 = test();
            System.out.println("num3 = " + num3); //1 
        }
    public static int test(){
            int result = 0;
            try {
                result = 1/1;
                System.out.println("result = " +result); //1
                
                return result;//(1)先把1,load到“方法的返回值存放区”(3)再结束当前方法,返回“方法的返回值存放区”的值
            } catch (Exception e) {
                return result;
            }finally{
                result++;//(2)result变量自增,变成2,这个2就不会放到“方法的返回值存放区” //如果变成return result++; 结果还是1 ;如果是return 3; 它就变成3了
                System.out.println("result = " + result); //2
            }

    * 结论:
    * (1)finally中的部分无论如何都要执行
    * (2)如果finally中有return,以finally中的return语句为主
    * (3)如果finally中无return,以try或catch中的return语句为主
    */

    考到try...catch...finally和return一起的时候:
    (1)finally中代码,无论如何一定要执行,不管是否发生异常,也不管是否catch住异常;
    (2)如果finally中没有return语句,那么就先执行finally,然后再回去执行try或catch中的return语句,第二个作用“结束当前方法”,返回值不受finally影响;
    (3)如果finally中有return语句,那么就执行finally中的return语句,相当于try和catch中return语句“失效”。

    throws

    throws:显式声明当前方法中,没有处理的异常,由调用者来处理,特别是编译时异常

    如果方法中有产生编译时异常,而又未处理,那么必须加throws声明,否则编译不通过

    如果方法中有产生运行时异常,而又未处理,那么可以加throws也可以不加,因为编译期间检测不到运行时异常,编译可以通过。

    * throws* 1、用于在声明方法时,显式的声明当前方法中没有处理的异常,要调用者来处理。
     * 调用者在使用有throws的方法时,用try...catch就知道该catch什么更具体异常,否则就按Exception
     用上throws(你得知道要抛出的是什么异常如ArithmeticException),写在方法名的后边,你再try...catch.. 选择try里边的代码右键选择Sound with 选择try,
    它就知道要抛什么异常了,不然它只会抛Exception异常。
    * * 2、语法格式: * 【修饰符】 返回值类型 方法名(【形参列表】)throws 异常列表{ * } * * 异常列表可以写好几个,用,分割 * * 3、关于方法重写 * (1)方法名和形参列表必须相同 * (2)返回值类型 * 基本数据类型和void:必须一致 * 引用数据类型:<= 子类重写方法的返回值类型<=父类被重写方法的返回值类型 * (3)权限修饰符:>= 子类重写方法的权限修饰符的可见性范围 >= 父类被重写方法的权限修饰符的可见性范围 * (4)其他修饰符: 哪些不能重写 static,final,private * (5)抛出的异常列表的类型:<= 子类重写方法抛出的异常类型 <= 父类被重写方法抛出的异常类型 */
    public class TestThrows {
    
        public static void main(String[] args) {
            
                try {
                    divide(1, 0);
                } catch (ArithmeticException e1) {
                    e1.printStackTrace();
                }
                
            
            
            try {
                copy("1.txt", "2.txt");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
                
            Father f = new Son();//多态引用
            
            try {
                f.test(); //编译时按照父类Father,运行时按子类Son,子类抛出RuntimeException异常,Exception要能够捕获到
            } catch (Exception e) {  //反过来按照子类抛出的Exception,这个时候发现catch就捕获不了
                e.printStackTrace();
            }
            
    
        }
        
        public static int divide(int a, int b) throws ArithmeticException{
            return a/b;
        }
        
        public static void copy(String srcFilePath, String destFilePath) throws FileNotFoundException{
            FileInputStream fis = new FileInputStream(srcFilePath);
            FileOutputStream fos = new FileOutputStream(destFilePath);
            
        }
        
    
    }
    
    class Father{
        public void test()throws Exception{
            
        }
    }
    class Son extends Father{
        public void test() throws RuntimeException{  //子类的抛出的异常类型要比父类的小
                                    //要保证子类抛出的异常父类能够接住
        }
        
    }
    View Code

    throw用于手动抛出异常对象

    * 大多数异常对象是JVM根据情况抛出。有的时候需要手动抛出异常,
    * throw:用于手动抛出异常对象
    * 语法结构:
      throw 异常对象;
       可以代替return语句,即带回异常信息,而且可以结束方法的执行

    public class TestThrow {
    
        public static void main(String[] args) {
            Account account = new Account();
            
            try {
                account.withdraw(100);
                System.out.println("取款成功");
            } catch (Exception e) {
                System.out.println(e.getMessage()); // 打印的是条件不满足时抛出的异常,给用户看的
                //e.printStackTrace(); //直接打印出红色异常信息,给开发者看的;
                
            }
            System.out.println("余额为:" + account.getBalance());
        }
    
    }
    
    class Account{
        private double balance = 1000;
        public double getBalance() {
            return balance;
        }
        public void setBalance(double balance) {
            this.balance = balance;
        }
        public void withdraw(double amount){
            if(amount < 0){
                            //Illegal不合法,Argument参数
                IllegalArgumentException e = new IllegalArgumentException("取款金额输入有误");
                throw e;
            }if(amount > balance){
                throw new RuntimeException("余额不足");
            }
            balance -= amount;
        }
    }

    自定义异常:

    * (1)要继承Throwable或它子类
    * 一般都继承Exception(编译时异常),或者RuntimeException(运行时异常)
    * (2) 异常名要见名知意
    * (3)尽量保留父类的两个构造器:一个是无参构造,一个是为message赋值的构造器
    * (4)自定义异常必须手动用throw来抛出,JVM无法给你自动抛出
    *
    * 一个异常:
    * (1)类型要见名知意
    * 例如:ArrayIndexOutOfBoundsException
    * ClassCastException
    * FileNotFoundException
    *
    * (2)自己的message消息
    * 异常对象名.getMessage()可以获取

    (3)堆栈跟踪信息
    * 异常对象经历的抛出路线,从哪个方法到哪个方法
    * 异常对象名.printStackTrace(); //Trace痕迹

    * System.err:异常信息,默认是红色的
    * System.out:普通信息
    * System.err和System.out是两个线程,谁先抢到谁先打印

    public class TestMyException {
    
        public static void main(String[] args) {
            
            try {
                regist("admin", 22, "123@qq.com");
                System.out.println("注册成功");
            } catch (UsernameExistException e) {
                e.printStackTrace();
                System.out.println(e.getMessage());
            }
        }
        
        public static void regist(String username, int age, String email) throws UsernameExistException{
            //做一个假的注册,假设我的数据库已经存"admin"
            if("admin".equals(username)){
                throw new UsernameExistException("用户名已存在");
            }
        }
    }
    
    class UsernameExistException extends Exception{
        
        public UsernameExistException(){
            super();
        }
        public UsernameExistException(String message){
            super(message);
        }
        
    }

    异常类型

    //下标越界
    public class TestArrayIndexOutOfBoundsException {
        public static void main(String[] args) {
            int[] arr = new int[0];
            
            try {
                System.out.println(arr[0]);
            } catch (Exception e) {
                e.printStackTrace();//标准的异常信息的打印方法,信息比较全,(1)类型(2)message(3)堆栈跟踪信息
                //
                System.out.println(e.getMessage());//只有message
            }
        }
    }
    View Code

    运行时异常
    异常栈e.printStank

    NullPointerException:空指针异常,当对象是null,却用对象调用方法,属性等。
    ArrayIndexOutOfBoundsExceptiom:数组下标越界异常,当下标的值超过[0,数组的长度-]的范围
    ClassCastException:类型转换异常,当对象不是该类型的实例时
    NumberFormatException:数字格式化异常,当把一个非数字的字符串转为数字
    ArithmeticException:算术异常,例如当除一个0时


    Java可能导致内存泄露的错误代码或者用简单代码演示内存溢出

    public class TestOutOfMemoryError {
        public static void main(String[] args) {
            Object[] arr = new Object[Integer.MAX_VALUE];
            
            System.out.println("Integer.MAX_VALUE =" + Integer.MAX_VALUE);
        }
    }
    java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    
    ----------------------------------------------------------------------------------
    public class TestStackOverflowError { public static void main(String[] args) { test(); } public static void test(){ test(); } } java.lang.StackOverflowError

    错误异常从最下看
    最后一个Caused by :xxx,然后再从下往上

  • 相关阅读:
    nginx2
    nginx1
    将Tomcat设置为自动启动的服务最快捷方法
    keepalived VS zookeeper
    Linux CentOS 7 下 Apache Tomcat 7 安装与配置
    使用curl 命令模拟POST/GET请求
    netty3---传统IO,NIO,nettyIO
    个人或小型企业站该如何选择服务器?
    如果你不懂备案,那我简单点跟你说
    SAE Java相关问题小结
  • 原文地址:https://www.cnblogs.com/shengyang17/p/10031596.html
Copyright © 2011-2022 走看看