zoukankan      html  css  js  c++  java
  • TIJ读书笔记01-操作符

     

     

     

    概述

    操作符
    操作符接受一个或多个参数,并生成一个新值. 换句话说操作符作用于操作数,生成一个新值.有些操作符会改变操作数自身.
    这种效应我们叫做side effect.

    赋值
    赋值操作符”=”的意思是,取右值赋值给左值.

    右值可以是任意的常数,变量或者表达式(只要它能生成一个值). 但是左值必须是一个明确的已命名的变量. 也就是说必须有物理空间可以存储右值.

    赋值也就是值传递,无论任何数据类型都遵循这一规则,都是取右值复制给左值. 但是对于不同的数据类型,赋值会有两种神奇的效果:

    • 对基本数据类型的赋值:
      • 基本数据类型的赋值直接赋的是”值”,就是直接把一个地方的内容复制到了另外一个地方
      • 对右值而言,没有任何改变和影响
    • 对于引用类型的赋值:
      • 引用类型的赋值实际赋的是对象的”引用”,赋值完成后,左值和右值都是同一个对象的引用.
      • 对于之后的两个变量来说,实际指向了同一个对象所以都可以对该对象进行操作.

    String类型是一种比较奇葩的类型. String s1="aaa";首先String类型是不可变的类型. 比如这么一条语句,执行过程是先在常量池中开辟一块内存区域,存入”aaa” 然后将s1指向这块常量池中的这个区域.
    所以对于下面这段代码,最后s1和s2分别会打印什么呢?

    String s1="aaa";
    String s2=s1;
    s2="bbb";

    s1是aaa,s2是bbb. 基础原则就是String类型是不可变的. 赋值过程很奇葩,就像上面说的一样.

    关系操作符和逻辑操作符

    关系操作符和逻辑操作符都会生成一个boolean值. 但是java中的布尔类型就是布尔类型,底层咋实现的我不知道,与C/C++中非0则true的实现不一样.

    关系操作符中的等于==和不等于!=
    在java中==操作符对于基本数据类型而言比较的是值,对于引用数据类型而言,比较的是”引用”.

        @Test
    public void equalTest(){
    Integer i1= new Integer(47);
    Integer i2 = new Integer(47);
    System.out.println(i1==i2);//false
    System.out.println(i1.equals(i2));//true

    MyInteger myI1= new MyInteger(47);
    MyInteger myI2 = new MyInteger(47);

    System.out.println(myI1==myI2);//false
    System.out.println(myI1.equals(myI2));//false
    }

    上面这段代码就很清楚了,对于引用类型而言,i1和i2虽然都是Integer并且值为47. 但是其所指向的引用是不一样的. 所以==返回false. 但是euqals方法却返回true.因为Integer类型重写了queals方法. 像下面这个我自己创建了一个类,没有重写equals方法,那么equals方法默认行为还是比较引用.

    什么事儿都逃不过一个理字, 基础数据类型的值是直接存放在栈上的,首先它没有引用.
    另外即使java中所谓的引用就是C/C++中的指针,甚至是内存地址(当然它不是),每个变量存放的地址是不一样的,那比较它是没有任何意义.
    对于”类”类型. 比较其”值”是没有意义的. 堆中不同的两个内存区域,即使存放的内容一毛一样,那也还是两块内存区域. 再者说,对于”类”类型(暂且这样叫吧,我也不知道它该叫啥,精神领会),绝大部分是用户自己定义的,java编译器不是神仙,不可能知道你定义的”类”类型里到底是个啥,它也揣摩不透你的比较逻辑.所以,所有类的祖宗Object类中给出了一个可以让你重写的equals方法. 给了你足够的自由.

    逻辑操作符
    逻辑操作符就那仨,与或非. 由于java布尔类型的特殊实现, 逻辑操作符无法作用于布尔类型之外的任何数据类型.
    如果是在应该使用String值的地方使用了布尔类型,那么布尔类型会转成适当的String类型.

    关于逻辑操作符,有个乱路机制. 也就是说一旦可以明确无误的缺点一个表达式的值,就不会再计算后面的部分了.

    public class ShortCircuit {
    public static boolean fun1(int val){
    System.out.println("fun1("+val+")");
    System.out.println("result:" + (val>1));
    return val>1;
    }

    public static boolean fun2(int val){
    System.out.println("fun2("+val+")");
    System.out.println("result:" + (val>4));
    return val>4;
    }

    public static boolean fun3(int val){
    System.out.println("fun3("+val+")");
    System.out.println("result:" + (val>5));
    return val>5;
    }
    }

    @Test
    public void logicalTest(){
    int i =3;
    boolean b = ShortCircuit.fun1(i)&&ShortCircuit.fun2(i)&&ShortCircuit.fun3(i);
    System.out.println(b);
    }
    //output:
    /*
    fun1(3)
    result:true
    fun2(3)
    result:false
    false
    */

    上面这例子可以看到,计算到fun2的时候,就可以确定这个逻辑表达式是false了. 所以就不会再往下计算了.

    这让我想起来一件事儿,高中的时候,当我一本正经的在听老师讲题的时候. 同桌哥们在鼓捣其他事情. 我提醒他好好听讲,他问我,讲这题你会不.我说会呀. 他说,既然你会了干嘛还听它呢. 想想很有道理,于是打瞌睡去了…
    当已经能明确确定这个表达式的值的时候,还往下计算,除了浪费资源之外还有什么用呢.

    位操作符

    位操作符按照剧本应该不会出现在java中,这种运算跟java屏蔽底层细节的画风严重不符,我也不明白它在java中有什么作用. 但是据说java当年是为了嵌入电视机机顶盒开发的,所以这种面向底层的操作还是被保留下来了.

    移位操作符

    • 左移<<,低位补0.
    • 有符号右移>>,有符号的意思就是使用符号扩展,如果符号为正,则高位插入0 如果符号为负,则高位插入1;
    • 无符号右移>>>,无论符号正负,高位都插入0

    对于char,byte和short类型,在移位操作前都会被转换成int类型.

    原码,反码,补码
    整数在计算机中的存储采用反码的形式.为什么采用反码呢,因为在使用反码的时候,计算逻辑是最简单的(因为不用区分符号位),而且不会出现0的两种编码形式.

    原码就是符号位+真值. 整数符号位是0 负数符号位是1.
    反码:正数的反码是其自身. 负数的反码是符号位不变,其他位取反
    补码:正数的补码是其自身,负数的补码是符号位不变,其他位取反然后加1.

    http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html 更详细的参见这个.

    类型转换

    java中向上转型不需要特殊声明. 向下转型需要显式声明.
    向下转型的时候,可能发生截尾. 如果需要舍入,则需要使用java.lang.Math下的round()方法.

    关于类型转换还有两点:

    • 基本数据类型在和String一起拼接的时候,会调用toString方法,将其转换成String类型.
    • 不同的数字类型一起运算的时候,表达式中最大的数据类型决定了最终运算结果的数据类型.

    java中没有sizeof()操作符. 因为这玩意儿不需要sizeof()… 下层是jvm,平台移植的问题由jvm来处理,不需要程序员去考虑这些事情.

  • 相关阅读:
    ASP.NET MVC使用Bootstrap系列(5)——创建ASP.NET MVC Bootstrap Helpers
    Discuz!NT中集成Memcached分布式缓存
    Memcached 两款.NET客户端的郁闷事儿
    分布式缓存BeIT Memcached简介
    .NET平台上的Memcached客户端介绍(Memcached Providers)
    PhantomJs 与 Casperjs
    ES5 Object.defineProperties / Object.defineProperty 的使用
    关于每天必做、且需要立刻执行、立刻培养的事
    我最喜欢的模板jade(pug)学习和使用
    前端 使用 crypto-js 对数据进行对称加密
  • 原文地址:https://www.cnblogs.com/thecatcher/p/5827847.html
Copyright © 2011-2022 走看看