4.3.1变量命名有哪些规则?
- java规定标识符只能是字母,数字,下划线_,和$组成,并且标识符的第一个字符不能是数字。
- 此外标识符也不能包含空白字符(换行,空格和制表符)
- java中变量名区分大小写。
4.3.2break,continue,以及return有什么区别?
- break:用于直接强行跳出当前循环,内层循环。
- continue:用于停止当次循环,回到循环起始处,进入下一次循环操作。
- return语句是一个跳转语句,用来标识从一个方法返回。
如何跳出多层循环:在多重循环的外面定义一个标识
package cn.itcast.demo;
public class test {
public static void main(String[] args) {
//在多重循环的外面定义一个标识
out:
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if(j >= 2){
break out;
}
System.out.println(j);
}
}
System.out.println("break");
}
}
引申:java语言中是否存在goto关键字?
虽然关键字goto作为java的 保留字,但目前并没有在java中使用。
4.3.3final,finally和finalize有什么区别?
1. final:用于声明属性,方法和变量,分别标识属性不可变,方法不可覆盖,类不可被继承。
问题:
final属性,被final修饰的变量不可变,那是引用不可变呢还是对象不可变呢?
package cn.itcast.demo;
public class Test1 {
public static void main(String[] args) {
final StringBuffer s = new StringBuffer("Hello");
s.append(" world");
System.out.println(s);
}
}
package cn.itcast.demo;
public class Test1 {
public static void main(String[] args) {
final StringBuffer s = new StringBuffer(" Hello");
s = new StringBuffer("Hello wold");//xxxx编译期间错误
}
}
结论:final指的是引用不可变,即它只能指向初始时指向的那个对象,而不关心对象内容的变化。所以,被final修饰的变量必须被初始化。
注意:一个类不能即被声明为abstract,又被声明为final
2. finally作为异常处理的一部分,只能用在try/catch语句中,并且附带一个语句块,标识这段语句最终一定会被执行,经常用在需要释放资源的情况下。
例1:
Connection conn;
Statement stat;
try{
conn = DriverManager.getConnection(url1,userName,password);
stat = conn.createStatement();
stat.executeUpdate(update);//执行一条update语句,此时出现异常
stat.close();
conn.close();
}catch(Execption e){
}
如果程序运行过程中没有发生异常,那么数据库的连接能够得到释放,程序运行没有问题。
如果执行update语句时出现异常,后面的close()方法将不会被执行,数据库的连接不会被释放。如果这样的程序长期运行,将会耗光数据库的连接资源。
通过使用finally可以保证在任何情况下数据库的连接资源都能够被释放。
例2:
Connection conn;
Statement stat;
try{
conn = DriverManager.getConnection(url1,userName,password);
stat = conn.createStatement();
stat.executeUpdate(update);//执行一条update语句,此时出现异常
stat.close();
conn.close();
}catch(Execption e){
}finally{
if(stat!=null){
stat.close();
}
if(conn!null){
conn.close();
}
}
3. finalize是Object类的一个方法,在垃圾回收器执行时会调用回收对象的finalize()方法。
注意:
一旦垃圾回收器准备好释放对象占用的空间,将首先调用其finalize方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的空间。
jdk中哪些类是不能继承的?
用final关键字修饰的类,如String,StringBuffer等。
4.3.4assert有什么作用?
断言(assert)是一种软件调试的方法。
主要作用:对一个boolean表达式进行检查,一个正确运行的程序必须保证boolean表达式的值为true,若boolean表达式的值为false,说明程序已经处于不正常状态,系统需要提供警告信息并退出程序。
assert的两种表达式:
1)assert expression1:
2)assert expression1:expression2
其中expression1表达一个boolean表达式,expression2标识一个基本类型或者一个对象。
public class Test{
public static void main(String[] args) {
assert 1+1 ==2;
System.out.println("assert1 ok");
assert 1+2 ==3:"assert faild,exit";
System.out.println("assert2 ok");
}
}
当执行指令:javac Test.Java和java -ea Test(打开ea开环)时,输出结果:
assert1 ok
Execption in thread “main” Java.lang.AssertionError:assert faild,exit at Test.main(Test.Java:5)
assert的应用范围:
1)检查控制流
2)检查输入参数是否有效
3)检查函数结果是否有效
检查程序不变量。
4.3.5static关键字有哪些作用?
java语言中,static主要有四种使用情况:成员变量,成员方法,代码块和内部类
static成员变量
java中没有全局的概念,但是可以通过static达到全局的效果
对静态变量的引用有两种方法:类.静态变量;对象.静态变量
java语言中不能在方法体中定义static变量。
package cn.itcast.demo;
public class TestAtribute {
public static int staticInt = 0;
public int nonStaticInt = 0;
public static void main(String[] args) {
TestAtribute t = new TestAtribute();
System.out.println("t.staticInt=" + t.staticInt);
System.out.println("TestAtribute.staticInt=" + TestAtribute.staticInt);
System.out.println("t.nonStaticInt=" + t.nonStaticInt);
System.out.println("对静态变量和实例变量分别+1");
t.staticInt++;
t.nonStaticInt++;
TestAtribute t1 = new TestAtribute();
System.out.println("t1.staticInt=" + t1.staticInt);
System.out.println("TestAtribute.staticInt=" + TestAtribute.staticInt);
System.out.println("t1.nonStaticInt=" + t1.nonStaticInt);
}
}
static成员方法:
static方法中不能使用this和super关键字,不能调用非static方法,只能访问所属类的静态成员变量和成员方法。
static一个很重要的用途是实现单例模式,只有一个实例。
为了实现这一功能,必须隐藏类的构造函数,即把类的构造函数声明为private,并提供一个创建对象的方法。
由于构造对象被声明为private,外界无法直接创建这个类型的对象,只能通过该类提供的方法来获取类的对象,
要达到这样的目的,只能把创建对象的方法声明为static,程序示例如下:
package cn.itcast.demo;
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
static代码块
static静态代码块经常被用来初始化静态变量。
package cn.itcast.demo;
public class Test3 {
private static int a;
static{
Test3.a=4;
System.out.println(a);
System.out.println("static block is called");
}
public static void main(String[] args) {
}
}
static内部类
注意:只有内部类才能被定义为static
Java里面static一般用来修饰成员变量或函数。但有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。被static修饰的内部类可以直接作为一个普通类来使用,而不需实例一个外部类(见如下代码)
主要是比较 静态内部类 和 非静态内部类 的区别 代码走起
测试静态内部类
package cn.itcast.demo1;
public class OuterClass {
//静态内部类
public static class InnerClass{
InnerClass(){
System.out.println("============= 我是一个内部类'InnerClass' =============");
}
}
}
package cn.itcast.demo1;
//测试静态内部类
public class TestStaticClass {
public static void main(String[] args) {
// 不需要new一个OutClass
new OuterClass.InnerClass();
}
}
如果没有用static修饰InterClass,则只能按如下方式调用
package cn.itcast.demo2;
public class OuterClass {
//内部类
public class InnerClass{
InnerClass(){
System.out.println("============= 我是一个内部类'InnerClass' =============");
}
}
}
package cn.itcast.demo2;
//测试静态内部类
public class TestNoStaticClass {
public static void main(String[] args) {
// OutClass需要先生成一个实例
OuterClass oc = new OuterClass();
oc.new InnerClass();
}
}
静态内部类和非静态内部类之间到底有什么不同呢?下面是两者间主要的不同。
(1)内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。(这一点上面的代码已经表示了)
(2)非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。他只能访问外部类的静态成员。(这是两种内部类对于内部类的外嵌类的数据访问区别)
(3)一个非静态内部类不能脱离外部类实体被创建(这个跟第一点有些重复,个人感觉),一个非静态内部类可以访问外部类的数据和方法,因为它就在外部类里面。(这个跟第二点也有点重复)
package cn.itcast.demo1;
public class OuterClass {
private static String msg = "GeeksForGeeks";
//静态内部类
public static class InnerClass{
//静态内部类只能访问外部类的静态成员
InnerClass(){
//试着将msg改成非静态的,这将导致编译错误
System.out.println("============= 我是一个静态内部类'InnerClass' =============" + msg);
}
}
}
package cn.itcast.demo1;
//测试静态内部类
public class TestStaticClass {
public static void main(String[] args) {
// 不需要new一个OutClass
new OuterClass.InnerClass();
}
}
试着将msg改成非静态的,这将导致编译错误
package cn.itcast.demo2;
public class OuterClass {
private static String msg = "GeeksForGeeks";
private String msg1 = "非静态变量";
//非静态内部类
public class InnerClass{
//不管是静态方法还是非静态方法都可以在非静态内部类中访问
InnerClass(){
System.out.println("============= 我是一个非静态内部类'InnerClass' =============" + msg
+ "\t" + msg1);
}
}
}
package cn.itcast.demo2;
//测试静态内部类
public class TestNoStaticClass {
public static void main(String[] args) {
// OutClass需要先生成一个实例
OuterClass oc = new OuterClass();
oc.new InnerClass();
}
}
引申:
1)什么是实例变量,局部变量,类变量,final变量?
实例变量如果没有显示初始化,则会有一个默认值
局部变量:在方法中定义的变量,在使用前必须初始化
final变量:标识这个变量为常量,不能被修改
2)static和final结合使用表示什么意思?
对于变量,表示一旦赋值不可修改
对于方法,表示不可覆盖
常见笔试题
package cn.itcast.demo3;
public class Test {
static final int i = 0;
public static int testStatic(){
//在java语言中,不能再成员函数内部定义static变量
//static final int i = 0;
//System.out.println(i++);//i++错误
System.out.println(i);
return 0;
}
public static void main(String[] args) {
// Test test = new Test();
Test.testStatic();
}
}
4.3.6使用switch时有哪些注意事项?
switch语句用于多分枝选择,switch(expr),expr必须是int或能够被隐式转换为int的byte,short,和char类型,
但是long,float,double,String类型除非强制转换,否则会直接报错
例1
public class Test{
public static void main(String[] args) {
float a = 0.123f;
switch (a) {//xxxx编译错误,a不是整型或字符类型变量。
case 1:
break;
default:
break;
}
}
}
switch对应的是case语句:case之后可以是直接的常量数值,1,2,
也可以是常量计算时1+2;
还可以是final型的变量,final int a = 0;
但不能是变量或者带有变量的表达式,例如i*2
更不能是浮点整数1.1或者2.0等。
switch(fromWay){
case 2-1://正确
....
case a-2://错误
.....
case 2.0://错误
.....
}
随着java的发展,switch支持String类型了
package cn.itcast.demo3;
public class TestString {
public void test(String str){
switch (str) {
case "hehao":
System.out.println("hehao");
break;
case "hehao1":
System.out.println("hehao1");
break;
case "hehao2":
System.out.println("hehao2");
break;
default:
System.out.println("default");
break;
}
}
public static void main(String[] args) {
TestString t = new TestString();
t.test("hehao");
}
}
本质上来讲,switch对字符串的支持,其实是int类型值的匹配。实现原理如下:
通过对case后面的string对象调用hashCode()方法,得到一个Int类型的hashCode值,然后用这个hash值来唯一标识这个case.
当匹配时,首先调用这个字符串的hashCode函数,获取一个hash值,匹配所有的case;如果匹配成功,接着会调用字符串的String.equals方法进行匹配。
所有String不能为null,case语句中的str也不能为null.
注意:
1)必须在case语句后添加break语句,否则会顺序执行。
package cn.itcast.demo3;
public class TestNobreak {
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.3.7volatile有什么作用?
java语言中,有时为了提高程序的运行效率,编译器会自动对其进行优化,把经常被访问的变量缓存起来,程序在读取这个变量的时候可能直接从缓存中读取。
问题:多线程编程时候,变量的值可能因为别的线程而改变了,而该缓存的值不会相应改变,造成程序读取的值与实际的值不符。
volatile是一个类型修饰符,被设计用来修饰被不同线程访问和修饰的变量。被volatile类型定义的变量,系统每次使用的时候都是直接从对应的内存中提取,而不会利用缓存。
public class MyThread {
private volatile Boolean flag;
public void stop(){
flag = false;
}
public void run(){
while(flag)
;//do something
}
}
以上示例代码是用来停止线程最常用的一种方法,
如果boolean类型的变量flag没有被声明为volatile,那么run方法判断flag可能使用的是缓存中的值,不能及时获取其他线程对flag的操作,导致线程不能及时地停止。
注意:
1)由于volatile不能保证操作的原子性,因此一般情况下不能使用volatile代替sychronized.
2)会阻止编译器对代码的优化,降低执行效率
4.3.8 instanceof 有什么作用?
判断左边的对象是否是右边对象的实例,返回boolean类型的数据
package cn.itcast.demo3;
public class Test1 {
public static void main(String[] args) {
String s = "Hello";
int[] a = {1,2};
if(s instanceof String){
System.out.println("true");
}
if(s instanceof Object){
System.out.println("true");
}
if(a instanceof int[]){
System.out.println("true");
}
}
}
4.3.9 strictfp有什么作用?
精确浮点:用来确保浮点数运算的准确性。
jvm在执行浮点数运算时,计算结果在不同平台或者厂商的虚拟机上可能有不同的结果,导致错误。
用strictfp来声明一个类,接口或方法,在所声明的范围内,标准是固定的。
注意:
1)当一个类被strictfp修饰时,所有方法都会自动被strictfp修饰。
package cn.itcast.demo3;
public strictfp class Test2{
public static void main(String[] args) {
float f = 0.12365f;
double d = 0.03496421d;
double sun = f+d;
System.out.println(sun);
}
}