Java学习笔记-《Java程序员面试宝典》-第四章基础知识-4.3关键字(4.3.4-4.3.6)

4.3.4assert有什么作用

断言(assert)作为一种软件调试的方法,提供了一种在代码中进行正确性检查的机制,目前很多开发语言都支持这种机制。它的主要作用是对一个boolean表达式进行检查,一个正确运行的程序必须保证这个boolean表达式的值为true,若boolean表达式的值为false,则说明程序已经处于一种不正确的状态下,系统需要提供警告信息并且退出程序。在实际的开发中,assert主要用来保证程序的正确性,通常在程序开发和测试时使用。为了提高程序运行的效率,在软件发布后,assert检查默认是被关闭的。
assert包括两种表达式,分别为assert expression1与assert experssion1:experssion2,其中,experssion1表示一个boolean表达式,experssion2表示一个基本类型或者是一个对象,基本类型包括boolean、char、double、float、int和long。一下是对这两个表达式的应用:

public class Test{
    public static void main(String[] args){
        assert 1+1 == 2;
        System.out.println("assert1 ok");
        assert 1+1 == 3:"assert faild,exit";
        System.out.println("assert2 ok");
    }
}

对于上述代码,执行指令javac Test.java与java Test时,程序的输出结果为:
assert1 ok
assert2 ok
对于上述代码,执行指令javac Test.java与java -ea Test时(java -ea Test的意思就是打开-ea开关),程序的输出结果为:
assert1 ok
Exception in thread “main” Java.lang.AssertionError:assert failed,exit
at Test.main(Test.Java:5)
assert的应用范围很多,主要包括:1>检查控制流2>检查输入参数是否有效3>检查函数结果是否有效4>检查程序不变量。虽然assert的功能与if判断类似,但是二者存在本质的区别:assert一般在调试程序时使用,但如果不小心用assert来控制了程序的业务流程,拿在调试结束后去掉assert就意味着修改了程序的正常逻辑,这样的做法是非常危险的;而if判断是逻辑判断,本身就可以用于控制程序流程。
需要注意的是,在Java语言中,assert与C语言的assert尽管功能类似,但也不完全一样,具体表现为两个方面的不同:1>Java语言是使用assert关键字去实现其功能,而C语言使用的是库函数2>C语言中的assert是在编译时开启,而Java语言中则是在运行时开启。

4.3.5static关键字有哪些作用

static关键字主要有两个作用:第一、为某特定的数据类型或对象分配单一的存储空间,而与创建对象的个数无关。第二、实现某个方法或属性与类而不是对象关联在一起,也就是说,在不创建对象的情况下就可以通过类来直接调用方法或使用类的属性。具体而言,在Java语言中,static主要有四种使用情况:成员变量、成员方法、代码块和内部类。
1>static成员变量
虽然Java语言中没有全局的概念,但是可以通过static关键字来达到全局的效果。Java类提供了两种类型的变量:用static关键字修饰的静态变量和不用static关键字修饰的实例变量。静态变量属于类,在内存中只有一个复制(所有实例都指向同一个内存地址)。只要静态变量所在的类被加载,这个静态变量就会被分配空间,因此就可以被使用了。对静态变量的引用有两种方式,分别为”类.静态变量”和”对象.静态变量”。
实例变量属于对象,只有对象被创建后,实例变量才会被分配内存空间。才能被使用,它在内存中存在多个复制。只能用”对象.实例变量”的方式来引用。
静态变量只有一个,被类拥有,所有对象都共享这个静态变量,而实例对象是与具体对象相关的。需要注意的是,与C++不同的是,在Java语言中,不能在方法体中定义static变量
2>static成员方法
与变量类似,Java类同时也提供了static方法与非static方法。static方法是类的方法,不需要创建对象就可以被调用,而非static方法是对象的方法,只有对象被创建出来后才可以被使用。
static方法中不能使用this和super关键字,不能调用非static方法,只能访问所属类的静态成员变量和成员方法,因为当static方法被调用时,这个类的对象可能还没被创建,即使已经被创建了,也无法确定调用那个对象的方法。同理,static方法也不能访问非static类型的变量。
static一个重要的用途是实现单例模式。单例模式的特点是该类只能有一个实例,为了实现这一功能,必须隐藏类的构造函数,即把构造函数声明为private,并提供一个创建对象的方法,由于构造对象被声明为private,外界无法直接创建这个类型的对象,只能通过该类提供的方法来获取类的对象,要达到这样的目的只能把创建对象的方法声明为static,程序示例如下:

class Singleton{
    private static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if( instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

用public修饰的static变量和方法本质上都是全局的,若在static变量前用peivate修饰,则表示这个变量可以在类的静态代码块或者类的其他静态成员方法中使用,但是不能在其他类中通过类名来直接引用。
3>static代码块
static代码块(静态代码块)在类中是独立于成员变量和成员函数的代码块的。它不在任何一个方法体内,JVM在加载类时会执行static代码块,如果有多个static代码块,JVM将会按顺序来执行。static代码块经常被用来初始化静态变量。需要注意的是,这些static代码块只会被执行一次。示例如下:

public class Test{
    private static int a;
    static{
        Test.a = 4;
        System.out.println(a);
        System.out.println("static blick is called");
    }
    public static void main(String[] args){
    }
}

程序运行结果为:
4
static block is called
4>static内部类
static内部类是指被声明为static的内部类,它可以不依赖于外部类实例对象而被实例化,而通常的内部类需要外部类实例化之后才能实例化。静态内部类不能与外部类有相同的名字,不能访问外部类的普通成员变量,只能访问外部类中的静态成员和静态方法(包括私有类型),示例如下:

public class Outer{
        static int n=5;
        static class Inner{
            void accessAttrFromOuter(){
                System.out.println("Inner:Outer.n = "+n);
            }
        }
        public static void main(String[] args){
            Outer.Inner nest = new Outer.Inner();
            nest.accessAttrFromOuter();
        }
}

运行结果:
Inner:Outer.n = 5
需要注意的是,只有内部类才能被定义为static。
引申:
实例变量:变量归对象所有(只有实例化后的对象才可以)。每当实例化一个对象时,会创建一个副本并初始化,如果没有显示初始化,那么会初始化一个默认值。各个对象中的实例变量互不影响。
局部变量:在方法中定义的变量,在使用前必须初始化。
类变量:用static修饰的属性、变量归类所有,只要类被加载,这个变量就可以被使用(类名.变量名)。所有实例化对象共享该变量。
final变量:该变量为常量,不能被修改。
static和final结合使用:在Java中,static和final结合使用,用来修饰成员变量与成员方法。对于变量,若使用static final修饰,则表示一旦赋值,就不可修改,并且通过类名可以访问。对于方法,若使用static final修饰,则表示该方法不可覆盖,并且可以通过类名直接访问。

4.3.6使用switch时有哪些注意事项

switch语句用于多分支选择,在使用switch(expr)时,expr只能是一个枚举常量(内部也是由整形或字符类型实现)或一个整数表达式,其中整数表达式可以是基本类型int或其对应的包装类Integer,当然也不包括不同的长度整形,例如short。由于byte、short和char类型的值都能够被隐式的转换为int类型,因此这些类型以及他们对应的包装类型都可以作为switch的表达式。但是,long、float、double、String类型不能够隐式地转换为int类型,因此他们不能被用作switch的表达式。如果一定要使用long、float或double作为switch的参数,必须将其强制转换为int类型才可以。
另外,与switch对应的是case语句,case语句之后可以直接是常量数值,例如1、2,也可以是一个常量计算式,例如1+2等,还可以是final类型的变量(final变量必须是编译时的常量),例如final int a = 0,但是不能是变量或带有变量的表达式,例如i *2等。当然更不能是浮点类型数,例如1.1或1.2/2等。示例如下:

switch(fromWay)
{
    case 2-1://正确
    ...
    case a-2://错误
    ...
    case 2.0://错误
    ...
}

随着Java语言的发展,在Java7中,switch开始支持String类型了,一下是一段支持String类型的示例代码:

public class Test {


    public void tesr(String str)
    {
        switch(str){
        case "hehao":
            System.out.println("hehao");
            break;
        case "xuepeng":
            System.out.println("xuepeng");
            break;
        default:
            System.out.println("default");
        }
    }
}

从本质上来讲,switch对字符串的支持,其实是int类型值的匹配。它的实现原理如下:通过对case后面的String对象调用hashCode()方法,得到一个int类型的hash值,然后用这个hash值来唯一标识这个case。那么当匹配时,首先调用这个字符串hashCode()函数,获取一个hash值(int类型),用这个hash值来匹配所有case,如果没有匹配成功,说明不存在;如果匹配成功,接着会调用字符串的String.equals()方法来进行匹配.由此可以看出,String变量不能为null,同时,switch的case字句中使用的字符串也不能为null。
在使用switch时,需要注意另外一个问题:一般必须在case语句结尾添加break语句。因为一旦通过switch语句确定了入口点,就会顺序执行后面的代码,知道遇到关键字break。否则,会执行满足这个case之后的其他case的语句而不管case是否匹配,知道switch结束或者遇到break为止、如果在switch中省略了break语句,那么匹配的case值后的所有情况(包括default)都会执行,实例如下:

public class Test{
    public static void main(String[] args){
        int x = 4;
        switch(x){
            case 1:System.out.println(x);
            case 2:System.out.println(x);
            case 3:System.out.println(x);
            case 4:System.out.println(x);
            case 5:System.out.println(x);
            default:System.out.println(x);
        }
    }
}

运行结果:
4
4
4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值