java认知盲点(1)

1. 数据类型转换:

(1)boolean 类型不参与转换
(2)默认转换
  A.从小到大
  B.byte,short,char – int – long – float – double
  C.byte,short,char之间不相互转换,直接转成int类型参与运算。

(3)强制转换
A.从大到小
B.可能会有精度的损失,一般不建议这样使用。
C.格式:目标数据类型 变量名 = (目标数据类型)(被转换的数据)

  思考题:
  A:下面两种方式有区别吗?
      float f1 = 12.345f;
      float f2 = (float)12.345;

相同无区别
B:下面的程序有问题吗,如果有,在哪里呢?
byte b1 = 3;
byte b2 = 4;
byte b3 = b1 + b2;
byte b4 = 3 + 4;
b = b1 + b2;是有问题的。
因为变量相加,会首先看类型问题,最终把结果赋值的也会考虑类型问题。
常量相加,首先做加法,然后看结果是否在赋值的数据类型范围内,如果不是,才报错。

class DataTypeDemo {
    public static void main(String[] args) {
        //定义了三个byte类型的变量,b1,b2,b
        //b1的值是3,b2的值是4,b没有值
        byte b1 = 3,b2 = 4,b;

        //b = b1 + b2; //这个是类型提升,所以有问题

        b = 3 + 4; //常量,先把结果计算出来,然后看是否在byte的范围内,如果在就不报错。
    }
}

类是类型转换的题目如下
short s=1;s = s+1;
short s=1;s+=1;
上面两个代码有没有问题,如果有,那里有问题。

第一个有问题第二个没有问题扩展的赋值运算符其实隐含了一个强制类型转换。
s += 1;
不是等价于 s = s + 1;
而是等价于 s = (s的数据类型)(s + 1);

class OperatorTest {
    public static void main(String[] args) {
        //short s = 1;
        //s = s + 1;//直接输出会报错,提示缺失精度,int--->short
        //System.out.println(s);

        short s = 1;
        s += 1; //好像是 s = s + 1;实际含有强转符号
        System.out.println(s);
    }
}

综上总结:
在编程中有显示转换和隐式转换两种,显示转换即强转,隐式转换是系统在计算过程中的自动转换
在编程中有些时候要考虑到隐式转换,它时常会带来意料之外的错误,在变量相加,会首先看类型
问题,最终把结果赋值的也会考虑类型问题哪怕是相同的short,byte,char类型在赋值时也会默认
转换成int类型

  C:下面的操作结果是什么呢?
      byte b = (byte)130;
分析过程:
    我们要想知道结果是什么,就应该知道是如何进行计算的。
    而我们又知道计算机中数据的运算都是补码进行的。
    而要得到补码,首先要计算出数据的二进制。
    A:获取130这个数据的二进制。
        00000000 00000000 00000000 10000010
        这是130的原码,也是反码,还是补码。
    B:做截取操作,截成byte类型的了。
        10000010 
        这个结果是补码。
    C:已知补码求原码。
                符号位     数值位
        补码: 1           0000010

        反码: 1           0000001

        原码: 1           1111110  
结果为-126     
  D:字符参与运算
      是查找ASCII里面的值
      ‘a’ ------- 97
      ‘A’ ------- 65
      ‘0’ ------- 48
  System.out.println(‘a’);
  System.out.println('a' + 1);
  E:字符串参与运算
  这里其实是字符串的连接
  System.out.println("hello"+'a'+1);
  System.out.println('a'+1+"hello");
  System.out.println("5+5="+5+5);
  System.out.println(5+5+"=5+5");

D、E对比输出分别为:a,98,helloa1,98hello,5+5=55,10=5+5
字符串数据和其他数据做+,结果是字符串类型。这里的+不是加法运算,而是字符串连接符。
字符型则是加法运算。

2.运算符号

(1)逻辑运算符
&(与),|(或),^(异或),!(非)
特点:逻辑运算符一般用于连接boolean类型的表达式或者值。
&逻辑与:有false则false。
|逻辑或:有true则true。
^逻辑异或:相同为false,不同为true。
举例:情侣关系。男男,男女,女男,女女
!逻辑非:非false则true,非true则false。

class OperatorDemo {
    public static void main(String[] args) {
        int a = 3;
        int b = 4;
        int c = 5;

        //&逻辑与
        System.out.println((a > b) & (a > c)); //false & false = false
        System.out.println((a > b) & (a < c)); //false & true = false
        System.out.println((a < b) & (a > c)); //true & false = false
        System.out.println((a < b) & (a < c)); //true & true = true
        System.out.println("---------------");

        //|逻辑或
        System.out.println((a > b) | (a > c)); //false | false = false
        System.out.println((a > b) | (a < c)); //false | true = true
        System.out.println((a < b) | (a > c)); //true | false = true
        System.out.println((a < b) | (a < c)); //true | true = true
        System.out.println("---------------");

        //^逻辑异或
        System.out.println((a > b) ^ (a > c)); //false ^ false = false
        System.out.println((a > b) ^ (a < c)); //false ^ true = true
        System.out.println((a < b) ^ (a > c)); //true ^ false = true
        System.out.println((a < b) ^ (a < c)); //true ^ true = false
        System.out.println("---------------");

        //!逻辑非
        System.out.println(!(a > b)); //!false = true
        System.out.println(!(a < b)); //!true = false
        System.out.println(!!(a > b)); //!!false = false
        System.out.println(!!!(a > b)); //!!false = true
    }
}

重点:&和&&的区别,同理|和||?
    A:最终结果一样。
B:&&具有短路效果。左边是false,右边不执行。

例子  
class OperatorDemo2 {
    public static void main(String[] args) {
        int a = 3;
        int b = 4;
        int c = 5;

        //&&双与
        System.out.println((a > b) && (a > c)); //false && false = false
        System.out.println((a > b) && (a < c)); //false && true = false
        System.out.println((a < b) && (a > c)); //true && false = false
        System.out.println((a < b) && (a < c)); //true && true = true
        System.out.println("----------------");

        int x = 3;
        int y = 4;

        //boolean b1 = ((x++ == 3) & (y++ == 4));
        //boolean b1 = ((x++ == 3) && (y++ == 4));
        //boolean b1 = ((++x == 3) & (y++ == 4));
        boolean b1 = ((++x == 3) && (y++ == 4));
        System.out.println("x:"+x);//单&:x:4。双&:x:4。
        System.out.println("y:"+y);//单&:y:5。双&:y:4。
        System.out.println(b1);//始终为false
    }
}

(2)~的计算
在计算机中所有的数据以补码的方式保存并计算
正数的补码为原码,负数的补码为原码的反码加一。
~为按位取反取反运算符,具体操作如下:

3   00000000 00000000 00000000 00000011(存储为补码)
~3  11111111 11111111 11111111 11111100(补码)
    10000000 00000000 00000000 00000011(反码)
-4  10000000 00000000 00000000 00000100(原码)
-----------------------------------------------------
-7  10000000 00000000 00000000 00001001(原码)
    11111111 11111111 11111111 11110111(存储的补码)
~-7 00000000 00000000 00000000 00001000(补码也是原码)
    结果为 8

(3)^的巧用
^的特点:一个数据对另一个数据位异或两次,该数本身不变。

        请自己实现两个整数变量的交换
class OperatorTest {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;

        System.out.println("a:"+a+",b:"+b);

        //方式1:使用第三方变量(开发中用的)
        int c = a;
        a = b;
        b = c;
        System.out.println("a:"+a+",b:"+b);
        System.out.println("------------");

        //方式2:用位异或实现(面试用)
        //左边:a,b,a
        //右边:a ^ b
        a = a ^ b;
        b = a ^ b; //a ^ b ^ b = a
        a = a ^ b; //a ^ b ^ a = b
        System.out.println("a:"+a+",b:"+b);

        //方式3:用变量相加的做法
        a = a + b; //a=30
        b = a - b; //b=10
        a = a - b; //a=20
        System.out.println("a:"+a+",b:"+b);

        //方式4:一句话搞定
        b = (a+b) - (a=b); //b=30-20=10,a=20
        System.out.println("a:"+a+",b:"+b);
    }
}   

(4)其他位符号
<<:左移 左边最高位丢弃,右边补齐0

:右移 最高位是0,左边补齐0;最高为是1,左边补齐1

:无符号右移 无论最高位是0还是1,左边补齐0

    3 << 2      3*2^2 = 3*4 = 12;

    24 >> 2     24 / 2^2 = 24 / 4 = 6
>>的移动:  -24 >> 2    -24 / 2^2 = 24 / 4 = -6
    计算出24的二进制:11000  
        原码:10000000 00000000 00000000 00011000  
        反码:11111111 11111111 11111111 11100111  
        补码:11111111 11111111 11111111 11101000  

        11111111 11111111 11111111 11101000  
        1111111111 11111111 11111111 111010(00) 补码  

        补码:1111111111 11111111 11111111 111010  
        反码:1111111111 11111111 11111111 111001  
        原码:1000000000 00000000 00000000 000110  

        结果:-6  

    >>>的移动:  -24 >>> 2      不能直接计算
        计算出24的二进制:11000  
        原码:10000000 00000000 00000000 00011000  
        反码:11111111 11111111 11111111 11100111  
        补码:11111111 11111111 11111111 11101000  

        11111111 11111111 11111111 11101000  
        0011111111 11111111 11111111 111010(00)  

        结果:  1073741818

    请用最有效率的方式写出计算2乘以8的结果?
            2 * 8

            2 << 3      
3.选择结构switch
先执行case,再执行default。
class SwitchTest {
    public static void main(String[] args) {
        int x = 2;
        int y = 3;
        switch(x){
            default:
                y++;
                break;
            case 3:
                y++;
            case 4:
                y++;
        }
        System.out.println("y="+y);
        System.out.println("---------------");

        int a = 2;
        int b = 3;
        switch(a){
            default://先执行case
                b++;//b = 4,由于没有break;停止则继续往下进行直至最后一句跳出。
            case 3: 
                b++; //b = 5
            case 4:
                b++; // b = 6
        }
        System.out.println("b="+b);
    }
}
4.跳转语句break;

跳出多层循环格式:
标签名:语句

class BreakDemo {
    public static void main(String[] args) {
        //在 switch 或 loop 外部中断
        //break;

        //跳出单层循环
        for(int x=0; x<10; x++) {
            if(x == 3) {
                break;
            }
            System.out.println("HelloWorld");
        }

        System.out.println("over");
        System.out.println("-------------");

        wc:for(int x=0; x<3; x++) {
            nc:for(int y=0; y<4; y++) {
                if(y == 2) {
                    //break nc;
                    break wc;
                }
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
4.二维数组

(1)二维数组的表示
数据类型[] []变量名 = new 变量类型 [m][n];
类是 int[] x,y[];
实际上等于int[] x;int[] y [];即一个一维数组x和一个二位数组y。

5.成员变量和局部变量的区别?
A:在类中的位置不同  
    成员变量:在类中方法外  
    局部变量:在方法定义中或者方法声明上  
B:在内存中的位置不同  
    成员变量:在堆内存  
    局部变量:在栈内存  
C:生命周期不同  
    成员变量:随着对象的创建而存在,随着对象的消失而消失  
    局部变量:随着方法的调用而存在,随着方法的调用完毕而消失  
D:初始化值不同  
    成员变量:有默认初始化值  
    局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。  

注意事项:  
    局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。  
6.构造方法

构造方法不能直接被显示调用,使用示例如下:

class Person {
    //姓名
    String name;
    //年龄
    int age;
    //国籍
    //String country;
    static String country;

    public Person(){ }

    public Person(String name,int age) { }

    public Person(String name,int age,String country) { }

    public void show() {
        System.out.println("姓名:"+name+",年龄:"+age+",国籍:"+country);
    }
}
class PersonDemo {
    public static void main(String[] args) {
        //创建对象1
        Person p1 = new Person("邓丽君",16,"中国");

        //错误: 找不到符号
        //Person p1 = new Person();
        //p1.Person("邓丽君",16,"中国");//无法被显示调用

        p1.show();
    }
}
7.static 关键字

实质是用来保留变量,即静态变量,而静态只能访问静态。
静态方法只能访问静态的成员变量和静态的成员方法

class Student {
    //非静态变量
    int num = 10;

    //静态变量
    static int num2 = 20;
}

class StudentDemo {
    public static void main(String[] args) {
        Student s = new Student();
        System.out.println(s.num);
        //System.out.println(Student.num);//错误: 无法从静态上下文中引用非静态 变量 num
        System.out.println(Student.num2);
        System.out.println(s.num2);
    }
}
阅读更多

没有更多推荐了,返回首页