• SCJP之赋值


    1:基本变量赋值与另一个基本变量

    public class Test {
        public static void main(String[] args) {
            int a=10;
            int b=a;
            b=30;
            System.out.println("a="+a);
            System.out.println("b="+b);
        }
    }

    输出结果:

    将数字10的位模式赋予int容器的变量a.然后把a内的位模式传入变量b。相当于把a复制一下,然后粘贴给b。所以这两个值没有任何关系了。修改其中一个,另一个没有影响。

    2:变量的作用域:

    class Layout {
        //静态变量
        static int s=343;
        //实例变量
        int x;
        {
            x=7;
            //初始块变量。属于局部变量
            int x2=5;
        }
        Layout(){
            x+=8;
            //是一个构造函数变量,属于局部变量
            int x3=6;
        }
        void doStuff(){
            //局部变量
            int y=0;
            //Z是一个块变量
            for(int z=0;z<4;z++){
                y+=z+x;
            }
        }
    }

    对于变量,我们分为4种基本作用域

      1):静态变量:生命周期最长。在加载类的时候就创建了。只要类在JVM中保持加载状态,就会一直存在。

      2):实例变量:短一些。在创建新实例的时候存在。直到实例被删除的时候消亡。

      3):局部变量:只要方法在栈上。就会存活下去。

      4):块变量:在执行的时候,才存在。

     作用域的几种错误表现:

      1):试图从静态上下文(通常是main()方法)访问一个实例变量。

    public class Test {
        int i;
        public static void main(String[] args) {
            i++;
            //Cannot make a static reference to the non-static field i
        }
    }

    解析:因为实例变量 i 还没有创建,相当于还没有出生。所以不能调用。

      2):试图从嵌套方法访问局部变量。

      

    public class Test {
        void go(){
            int i=4;
            i++;
        }
        void go2(){
            //i cannot be resolved to a variable
            i--;
        }
    }

    解析:因为局部变量 i 出了go()方法就死亡了。

    3:变量默认值

    public class Test {
        int j;
        public static void main(String[] args) {
            Test t=new Test();
            System.out.println(t.j);
            t.go();
        }
        void go(){
            int i=9;
            System.out.println(i);
        }
        
    }
    //当局部变量没有显示的赋予值的话,编译器不通过的。
    public class Test {
        int j;
        public static void main(String[] args) {
            Test t=new Test();
            System.out.println(t.j);
            t.go();
        }
        void go(){
            int i;
            System.out.println(i); //这样调用是错误的。因为不知道局部变量i是什么。
        }
    }

    实例变量:因为可以隐士的赋予0.所以可以直接调用。

      对象实例变量默认赋予null.所以使用前保证该引用不是Null即可。

      对于编译器来说:null是一个值。不可以在null引用上使用点运算符。因为它的另一端没有任何对象。null值:指引用变量没有引用堆上任何对象。与空的String(" ")是不同的。

    局部变量:不知道是什么值。所以不可以调用。所以局部变量总是在使用前进行显示初始化。可以不在同一行代码中。但是一定要初始化。局部变量可以初始化为null

    数组元素总是,总是,总是被赋予默认值。无论数组在哪里被声明或者实例化。

     4:对象引用。将一个引用变量赋予另一个引用变量

    public class Foo {
        public int i;
        public int j;
        
        public int getI() {
            return i;
        }
        public void setI(int i) {
            this.i = i;
        }
        public int getJ() {
            return j;
        }
        public void setJ(int j) {
            this.j = j;
        }
        Foo(){    }
        Foo(int i,int j){
            this.i=i;
            this.j=j;
            System.out.println(i+"||"+j);
        }
    }

    如果没有 this.i=i; this.j=j;  使用的时候:

    Foo f=new Foo(4,5);
     System.out.println(f.i);   输出结果就是0

    public class Test {
        public static void main(String[] args) {
            Foo f=new Foo(4,5);
            System.out.println("初始的Foo对象中的变量 i  f.i="+f.i);
             Foo f2=f;
             f2.i=30;
             System.out.println("将引用变量f赋予f2后   f2.i="+f2.i);
             System.out.println("将引用变量f赋予f2后   f.i="+f.i + "  after change to f2");
        }
    }

    输出结果:

    解析:将一个引用变量赋予另一个引用变量。这两个引用变量将拥有相同的位模式。该位模式引用堆上的一个具体对象。当f赋予f2后,f和f2拥有相同的值。但是只有一个Foo对象。因为这两个引用都是指向Foo对象的。所以不论谁进行修改,都是进行Foo对象的修改。

     对象引用赋值方式的一种例外:String对象。因为String对象是特殊处理的。String对象是不可变的。

    public class Test {
        public static void main(String[] args) {
            String i="java";
            System.out.println("i="+i);
            String j=i;
            System.out.println("j="+j);
            j="HelloWorld";
            System.out.println("修改后的j="+j+"修改后的i="+i);
        }
    }

    输出结果:

    修改后的j输出HelloWorld是因为是两个String对象。与以前的那个String对象不是同一个对象。

    5:向方法传递变量

    将对象变量传递到方法的时候,传递的是对象引用。而不是对象本身。根本没有传递实际的引用变量。而是该引用的一个副本。变量副本意味着获得该变量内的位副本,因此,当传递引用变量时,是在传递表示如何获得特定对象的位副本。换句话说,调用方法和被调用方法现在都具有该引用完全相同的副本,因此二者都将引用堆上完全相同的对象。(不是副本,是实打实的对象)

    public class ReferenceTest {
        public static void main(String[] args) {
            Dimension d=new Dimension(5,10);
            ReferenceTest rt=new ReferenceTest();
            System.out.println("使用方法modif()前  d.height="+d.height);
            rt.modify(d);
            System.out.println("使用方法modif()后  d.height="+d.height);
        }
        void modify(Dimension dim){
            dim.height=dim.height+1;
            System.out.println("dim="+dim.height);
        }
    }

    结果:

    解析:Dimension对象作为参数传入到modify()方法中。因为传入的是副本。对象引用d和对象引用dim都是指向Dimension对象的。所以dim修改了Dimension对象。d引用Dimension.值也进行改变。

    6:Java是按值进行传递的吗?  其实是传递一个变量的副本

    如果是基本变量,是按值进行传递的

    public class ReferenceTest {
        public static void main(String[] args) {
            ReferenceTest rt=new ReferenceTest();
            rt.modify(10);
        }
        void modify(int i){
            i=3;
            System.out.println("i="+i);
        }
    }

    输出结果:

    如果是对象类型。就不是按值传递。

     7:变量隐藏   (就是实例变量和局部变量冲突)

    有两种方式:1):直接声明一个相同名称的局部变量。
          2):作为变元的一部分声明一个相同名称的局部变量。

    public class Test {
        static int size=7;
        static void changeIt(int size){
            size =size+200;
            System.out.println("size in changeIt is="+size);
        }
        public static void main(String[] args) {
            //没有调用方法的时候,只有一个实例变量size
            System.out.println("size="+size);
            //调用方法,局部变量优先。
            changeIt(size);
            //调用完方法后,局部变量死亡,size没有进行修改。
            System.out.println("size in changeIt now is="+size);
            }
    }

    class Bar{
        int barNum=28;
    }
    class Foo{
        Bar myBar=new Bar();
        void changeIt(Bar myBar){
            myBar.barNum=99;
            System.out.println("myBar.barNum in changeIt a is"+myBar.barNum);
            myBar.barNum=199;
            System.out.println("隐藏对象引用后myBar.barNum="+myBar.barNum);
            myBar=new Bar();
            myBar.barNum=420;
            System.out.println("myBar.barNum in changeIt b is"+myBar.barNum);
    }
    }
    public class Test {
        public static void main(String[] args) {
            Foo f=new Foo();
            //还没有调用方法,只有一个变量,实例变量barNum;
            System.out.println(f.myBar.barNum);
            //调用方法后。局部变量把实例变量替换掉。
            f.changeIt(f.myBar);
            //调用方法后第一个局部变量进行修改。对象也跟着修改。为什么没有修改成420,因为不是一个对象
            System.out.println(f.myBar.barNum);
        }
    }

     输出结果:

  • 相关阅读:
    wait与sleep区别?
    oracle死锁查询
    atomic 原子操作的类
    买票问题
    0001.第一个多线程demo--分批处理数据
    01: JavaScript实例
    01: 运维工作梳理
    04: 使用BeautifulSoup封装的xss过滤模块
    04: 打开tornado源码剖析处理过程
    03: 自定义异步非阻塞tornado框架
  • 原文地址:https://www.cnblogs.com/bulrush/p/7280007.html
Copyright © 2020-2023  润新知