02-基础语法

基础语法

问:关键字和保留字

(1) Java关键字列表(依字母排序共50组)

abstract, assert, boolean, break, byte, case, catch, char, class, const(保留关键字), continue, default, do, double, else, enum, extends, 
final, finally, float, for, goto(保留关键字), if, implements, import, instanceof, int, interface, long, native, new, package, private, 
protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, try, void, volatile, while 

(2) 保留字列表(依字母排序共14组),Java保留字是指现有Java版本尚未使用,但以后版本可能会作为关键字使用

byValue, cast, false, future, generic, inner, operator, outer, rest, true, var, goto(保留关键字), const(保留关键字), null

注意:

(1) const和goto既是保留字又是关键字

(2) 除了const和goto,其余保留字和关键字是严格区分开的。

问:Java支持的数据类型有哪些?

Java语言支持8种基本数据类型是:byte、short、int、long、float、double、boolean、char;支持3种引用数据类型:类、接口、枚举和数组。

(1) Java中整数值默认为int型,如果要指定整数为long型需要加L;浮点数值默认为double型,如果要指定浮点数为float型需要加F。

float f=3.4;  //错误,3.4默认为double型。
float f=3.4F; //正确
float f=3;    //正确

(2) Java中在定义类的成员变量时可以对其初始化,如果不对其初始化,Java使用默认值对其初始化;而局部变量在使用前则必须进行初始化,JVM不会进行默认值初始化。

(3) Java中基本数据类型变量默认初始化值如表所示,引用变量默认初始化值为null。


图 2

例1:

int类型变量的默认值为0;Integer类型变量的默认值为null。

问:类型转换

(1) 各数据类型按容量大小(表数范围大小)由小到大排列为:byte\char\short -> int -> long -> float -> double

(2) 低级向高级是隐式类型转换;高级向低级必须强制类型转换,且可能丢失精度

例1:

double f = 1.2;
int value = (int)f; //结果为1,丢失了小数点部分

例2:

对于java类型变量char c,short s,float f,double d,表达式c*s+f+d的结果类型为double

(3) Java中char、byte、short之间不会发生隐式类型转换(需要强制转换);如果碰到char、byte和short参与运算时,会自动将这些值转换为int类型值然后再进行运算。

例1:

short s1 = 1; 
s1 = s1 + 1; // 编译错误:由于s+1运算结果为int型,再赋值给short类型s,编译器会报告需要强制类型转换的错误。

short s1 = 1; 
s1 += 1;    //编译正确:Java编译器会对+=特殊处理

short s = 16;
byte a2 = s; //错误

问:Java中的中文字符

Java语言中,中文字符所占的字节数取决于字符的编码方式,默认使用GBK编码方式。

当采用ISO8859-1编码方式时,一个中文字符占1个字节;

当采用GB2312或GBK编码方式时,一个中文字符占2个字节;

当采用UTF-8编码方式时,一个中文字符会占3个字节。

Java字符默认使用unicode编码,每个字符占用两个字节,所以char型变量可以存放一个中文字符。

Unicode字符编码标准是固定长度的字符编码方案。Unicode根据要编码的数据类型使用两种编码格式:8 位和16位。缺省编码格式是16位,即每个字符是16位(两个字节)宽。

注意:char与byte在Java和C++中的区别:

在C++中,char是基础数据类型,占1个字节;byte不是基础数据类型,一般定义为typedef unsigned char byte;也就是说,byte其实是unsigned char类型,那么也是占1个字节。不同的是,char可以表示的范围是-128-127,而byte可以表示的范围是0-255。

在java中,char和byte都是基础数据类型,其中的byte占1个字节,可以表示的范围是-128-127。而char占2个字节,可以表示的范围是’\u0000’-‘\uFFFF’。

例1:

Java中实现国际化应用常用的手段是利用ResourceBundle类。

这个题目解答没看懂

问:进制表示

  • 八进制: 012
  • 十六进制:0x12

问:源码、反码和补码

例1:

变量a是一个64位有符号的整数,初始值用16进制表示为:0Xf000000000000000;
变量b是一个64位有符号的整数,初始值用16进制表示为:0x7FFFFFFFFFFFFFFF。
则a-b的结果用10进制表示为多少?

计算机是用补码进行存储和计算的,因此a和b的初始值即为a和b在计算机中的补码形式,即:a的补码为0Xf000000000000000,b的补码为0x7FFFFFFFFFFFFFFF
0Xf000000000000000=1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0x7FFFFFFFFFFFFFFF=0111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111

a-b=a+(-b)
由于b是正数,原码与其补码相同,都为0x7FFFFFFFFFFFFFFF,则-b的原码为0xFFFFFFFFFFFFFFFF,是负数
现在求-b的补码,先对它的原码(除符号位外)各位取反得到-b的反码,然后反码尾部加1得到-b的补码,为
1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001

所以a-b=a+(-b)=
 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000+
 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001=
10111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001(最高位溢出,舍去,结果变成了正数)
则结果为0111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001=2^62+2^61+2^60+1

例2:

变量a是一个64位有符号的整数,初始值用16进制表示为:0x7FFFFFFFFFFFFFFF;
变量b是一个64位有符号的整数,初始值用16进制表示为:0x8000000000000000。
则a+b的结果用10进制表示为多少?

计算机中是以补码形式存储数据,则a和b的初始值即为a和b在计算机中的补码形式。
0x7FFFFFFFFFFFFFFF+0x8000000000000000=0xFFFFFFFFFFFFFFFF
结果最高位符号位为1,说明结果为负数,现在求结果的原码值。
保持符号位不变,补码减1,得到结果的反码;保持符号位不变,反码取反,得到结果的原码:-1

例3:

short a=128;
byte b=(byte)a;
此时,变量a,b的值分别为128和-128

计算机是用补码进行存储和计算的,Java中short占2个字节,16位,因此a在内存中补码形式为0000 0000 1000 0000
Java中byte占1个字节,8位。将short变量强制类型转换时会截断前8位,得到1000 0000,即为b的补码形式。
现在已知a的补码为10000000,求原码。因为最高位表示符号位,所以首先这个数为负数。
保持符号位不变,补码减1,得到结果的反码1111 1111;保持符号位不变,反码取反,得到结果的原码1 0000 0000:-128

问:常见的运算符 +,%,~,三目运算符,++,&&和&,>>和>>>

  • +:

例1:

public class Test {
    public static void main(String args[]) {
        System.out.println(8+8+"88"+8+8);  //168888
    }
}

例2:

若有定义语句:int a=10; double b=3.14;则表达式'A'+a+b 值的类型是double

例3:

假定x和y为double型,则表达式x=2,y=x+3/2的输出为3.000000
  • %:取模运算符,要求操作数为整型。

  • ~:按位取反运算符

例1:

若int j = 10; 则~j为多少?

计算机是用补码进行存储和计算的,因此10在计算机中补码存储为:00000000 00000000 00000000 00001010
~j操作是对j的补码取反,然后得到结果即为~j的补码:         11111111 11111111 11111111 11110101
现在通过~j的补码反推出~j的原码,~j最高位符号位为1,表明它是一个负数
保持符号位不变,补码减1,得到~j的反码:                  11111111 11111111 11111111 11110100
保持符号位不变,反码取反,得到~j的原码:                 10000000 00000000 00000000 00001011
换算为整数,~j大小为-11

公式:-n=~n+1,可以推出~n=-n-1,所以~10=-11
  • 三目运算符

例1:

boolean b=true?false:true==true?false:true;
System.out.println(b);  //false

例2:下列代码输出是什么?

public static void main(String[] args){
    boolean result1=true1()?true2():true3()==true4()?false1():true5();
    System.out.println(result1);
    boolean result2=false1()?true2():true3()==true4()?false2():true5();
    System.out.println(result2);
}
public static boolean true1(){
    System.out.print("true1  ");
    return true;
}
public static boolean true2(){
    System.out.print("true2  ");
    return true;
}
public static boolean true3(){
    System.out.print("true3  ");
    return true;
}
public static boolean true4(){
    System.out.print("true4  ");
    return true;
}
public static boolean true5(){
    System.out.print("true5  ");
    return true;
}
public static boolean false1(){
    System.out.print("false1 ");
    return false;
}
public static boolean false2(){
    System.out.print("false2 ");
    return false;
}

输出如下:
true1  true2  true
false1 true3  true4  false2 false

从输出结果可以看出例1中b=true?false:true...,true成立使得结果b为false,表达式返回,后面的表达式不再执行。

结论:(1) ==优先级大于三目运算符 (2) 写复杂表达式时,请记得加括号,便于阅读

  • ++

i=i++问题

Java使用了中间缓存变量机制,JVM运行这条语句时过程如下:

步骤1 JVM把i值拷贝到临时变量区;

步骤2 i值加1;

步骤3 返回临时变量区的值,注意这个值步骤1中没修改过的i值。

步骤4 返回值赋值给i,此时count值被重置成原来的值。

例1:

package algorithms.com.guan.javajicu; 
public class Inc { 
    public static void main(String[] args) { 
       Inc inc = new Inc(); 
       int i = 0; 
       inc.fermin(i); 
       i= i ++; 
       System.out.println(i);
    } 
    void fermin(int i){ 
       i++; 
    } 
}

程序输出结果为0

例3:

public class Test2{
    public void add(Byte b){
        b = b++;
    }
    public void test(){
        Byte a = 127;
        Byte b = 127;
        add(++a);
        System.out.print(a + " ");
        add(b);
        System.out.print(b + "");
    }
}

执行test()函数后,程序输出为:-128 127
  • &&和&

两者都可以用作逻辑与运算符。当运算符两边的表达式都为true时,整个运算结果才为true;否则只要有一边表达式为false,则运算结果为false。

两者的区别如下:

(1) &&具有短路的功能,若该运算符左边为false,运算符右边表达式不执行;而&作为逻辑与运算符时不具备短路功能,若该运算符左边为false,运算符右边表达式还会继续执行。

(2) &还可以作为按位与运算符,当&运算符两边的表达式是int类型时,&表示按位与操作。例如 0x31 & 0x0f = 0x01。

很多时候我们可能都需要使用&&而不是&。
例如在用户登录时验证用户名不是null且不是空字符串,应当写为:username != null &&!username.equals(""),二者的顺序不能交换,更不能用&运算符。
因为如果第一个条件不成立,根本不能进行字符串的equals比较,否则会报NullPointerException异常。

注意:运算符 | 和运算符 || 的差别也是如此。

  • <<

将一个数左移n位,相当于这个数乘以2的n次方

2 << 3 = 16
  • >>和>>>

>> 表示带符号右移,正数结果为正,高位补0;负数结果为负,高位补1

int x1=5>>2;
int x2=-5>>2;

5在计算机中补码表示为:  0 0000000 00000000 00000000 00000101
5为正数,5>>2,高位补0: 0 0000000 00000000 00000000 00000001,5为正数,符号位保留为0,结果x1=1
-5在计算机中补码表示为:  1 1111111 11111111 11111111 11111011
-5为正数,-5>>2,高位补1:1 1111111 11111111 11111111 11111110,-5为负数,符号位保留位1,结果x2=-2

>>> 表示无符号右移,左边空出的位以0填充

int y1=5>>>2;
int y2=-5>>>2;

5在计算机中补码表示为:  00000000 00000000 00000000 00000101
5>>>2,左边空出的位补0: 00000000 00000000 00000000 00000001,结果y1=1
-5在计算机中补码表示为: 11111111 11111111 11111111 11111011
-5>>>2,左边空出的位补0:00111111 11111111 11111111 11111110,结果为y2=1073741822

问:switch

switch(expr)中,expr是一个整数表达式,因此传递给switch和case语句的参数应该是byte、short、int、char或者其对应的封装类以及Enum类型(byte,short,char都可以隐式转换为int,因此也可以作为expr),long和String(在Java7中,也支持了String类型)都不能用于swtich表达式。

enum Var {
    LEFT, RIGHT
}

public static void main(String[] args) {
    Var e = Var.LEFT;
    switch (e) {
    case LEFT:
        System.out.println("----left-----");
        break;
    case RIGHT:
        System.out.println("----right-----");
        break;
    default:
        System.out.println("----stay around-----");
        break;
    }
}

在switch语句中,表达式的值不能是null,否则会在运行时抛出NullPointerException。在case子句中也不能使用null,否则会出现编译错误。

问:switch与break

switch结构中匹配的case子句中如果没有break跳出执行,那么程序执行完case子句后不会跳出,将会继续执行后续的case子句,直到遇到break跳出switch;如果一直没有遇到break,程序将一直执行到整个结构结束。

例1:

public class SwitchTest{//1
    public static void main(String[] args) {
        System.out.println(switchit(4));
    }
    public static int switchit(int x) {
        int j=1;
        switch (x) {
        case 1:j++;
        case 2:j++;
        case 3:j++;
        case 4:j++;
        case 5:j++;
        default:j++;
        }
        return j+x;
    }
}
程序将会输出8

例2:

public static int getValue(int i) {
    int result = 0;
    switch (i) {
    case 1:
        result = result + i;
    case 2:
        result = result + i * 2;
    case 3:
        result = result + i * 3;
    }
    return result;
}
调用getValue(2)将返回10

问:值传递和引用传递?

java内的传递都是值传递。

(1) 对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。

(2) 对引用型变量而言的,传递的是该对象地址的一个副本,所以对引用型变量进行操作会同时改变原对象。

例1:

public class Tester{
    public static void main(String[] args){
       Integer var1=new Integer(1);
       Integer var2=var1;
       doSomething(var2);
       System.out.println(var1.intValue());
       System.out.println(var1==var2);
    }
    public static void doSomething(Integer integer){
        integer=new Integer(2);
    }
}

程序运行输出如下:
1
true

例2:注意下一评论

问:可变参数

JDK 1.5开始,Java支持给一个方法传递同类型的可变参数,且只能指定一个可变参数。可变参数必须是方法的最后一个参数,任何普通参数必须在可变参数之前声明。

public void fun(int len, String ...str) {

}
分享到 评论