• Java编程思想(Chapter2、4、6)


    一切皆对象

    用引用操纵对象

    Java中操纵的标识符实际上是对象的“引用”。例如想要操纵一个字符串,则可以创建一个String引用。
    String s;
    此处s只是一个引用。

    存储位置

    基本类型/对象的引用:堆栈
    对象: 堆

    作用域

    作用域由{}确定,决定了在其中定义的变量名的可见性以及生命周期。
    1 {
    2     int x =12;
    3     {
    4         int x = 96; //illegal
    5     }
    6 }

    非法,不能隐藏。

    {
        String s = new String("str");
    }
    引用s在作用域终点消失,而s指向的String对象仍然占据着内存空间,直到gc销毁。

    关于值传递还是引用传递的问题

    Java中只存在值传递
    1.基本类型的传递
      没有任何疑问,传值
    2.对象的传递
      参数传递时,只存在传递基本类型和对象引用的问题,并不会直接传对象本身

    一个方法不能修改一个基本数据类型的参数

    一个方法可以改变一个对象参数的状态

    一个方法不能让对象参数引用一个新的对象

    参考知乎话题:java到底是值传递还是引用传递?传送门
    对于参数是String类型,不修改原的原因在于 String 对象是final类型。

    初始化与清理

    初始化顺序

    以一实例说明
    public class Tag {
        public Tag(int marker) {
            System.out.println("tag"+marker);
        }
    }
    public class Card {
        Tag tag = new Tag(1);
        public Card() {
            System.out.println("card()");
            tag3 = new Tag(33);
        }
        Tag tag2 = new Tag(2);
        void f(){
            System.out.println("f()");
        }
        Tag tag3 = new Tag(3);
    }
    public class Init01 {
        public static void main(String[] args) {
            Card card = new Card();
            card.f();
        }
    }

    Result

    tag1
    tag2
    tag3
    card()
    tag33
    f()
    View Code
    可以看出先进行变量的初始化,再进行构造器调用。

    在此基础上,如果还有静态数据时,顺序如何?

    public class Bowl {
        public Bowl(int marker) {
            System.out.println("bowl "+marker);
        }
        protected void f(int marker){
            System.out.println("f "+marker);
        }
    }
    public class Table {
        static Bowl b1 = new Bowl(1);
        public Table(){
            System.out.println("table()");
            b2.f(1);
        }
        void f2(int marker){
            System.out.println("f2 "+marker);
        }
        static Bowl b2 =new Bowl(2);
    }
    public class Cupboard {
        Bowl b3 =new Bowl(3);
        static Bowl b4 = new Bowl(4);
        Cupboard(){
            System.out.println("cup()");
            b4.f(2);
        }
        void f3(int marker){
            System.out.println("f3 "+marker);
        }
        static Bowl b5 = new Bowl(5);
    }
    public class Test {
        public static void main(String[] args) {
            System.out.println("create cup in main");
            new Cupboard();
            System.out.println("create cup in main");
            new Cupboard();
            t2.f2(1);
            t3.f3(1);
        }
        static Table t2 = new Table();
        static Cupboard t3 = new Cupboard();
    }

    Result

    bowl 1
    bowl 2
    table()
    f 1
    bowl 4
    bowl 5
    bowl 3
    cup()
    f 2
    create cup in main
    bowl 3
    cup()
    f 2
    create cup in main
    bowl 3
    cup()
    f 2
    f2 1
    f3 1
    View Code
    可以看出,先进行static静态数据的初始化(只执行一次),再普通变量的初始化,最后再调用构造器。

    数组的初始化

    每次访问数组时,都将进行数组的边界检测。

    复用类

    带参数的构造器

    如果类没有缺省的参数,或者想调用一个带参数的基类构造器,则必须用super显示地编写调用基类构造器的语句。
    public class C3 extends C2{
        public C3(int i) {
            super(i);//
            System.out.println("c3");
        }
        public static void main(String[] args) {
            new C3(1);
        }
    }
    class C1{
        public C1(int i) {
            System.out.println("c1");
        }
    }
    class C2 extends C1{
        public C2(int i) {
            super(i);//
            System.out.println("c2");
        }
    }
    此处,两个super(i)都是必须,不然会报错。

    初始化及类的加载

    public class Insect {
        protected int i = 9;
        protected int j;
        protected int x3 = print("static Insect.x3 init");
        public Insect() {
            System.out.println("i="+i+" ,j="+j);
            j =39;
        }
        private static int x1 = print("static Insect.x1 init");
        static int print(String s){
            System.out.println(s);
            return 47;
        }
    }
    public class Beetle extends Insect{
        private int k = print("Beetle.k init");
        public Beetle() {
            System.out.println("k="+k);
            System.out.println("j="+j);
        }
        private static int x2 = print("static Beetle.x2 init");
        public static void main(String[] args) {
            System.out.println("Beetle construct");
            Beetle beetle = new Beetle();
        }
    }

    Result

    static Insect.x1 init
    static Beetle.x2 init
    Beetle construct
    static Insect.x3 init
    i=9 ,j=0
    Beetle.k init
    k=47
    j=39
    View Code

    可以看出,先进行类的加载,先基类再子类。static变量/块执行于类的初始化时期。new之后按照 先初始化再构造器的顺序执行。

  • 相关阅读:
    信息产品是信息化理念的凝缩的精华
    自然科学技术表面上是反应人与自然的关系,更深层还是人与人之间的关系
    思与在,为何没有行
    haproxysocket 参数记录
    zabbix 监控 haproxy 记录
    Centos6.5安装OpenLDAP
    ansible mysql模块的使用今年
    haproxy 官方文档查看
    centos 7 部署 mysql 报错记录
    ansible playbook学习
  • 原文地址:https://www.cnblogs.com/zhaoww/p/5847176.html
Copyright © 2020-2023  润新知