zoukankan      html  css  js  c++  java
  • Java基础(二)--this关键字及初始化

    构造器:

      构造器的名称必须和类名完全相同,所以一般方法的"首字母小写"命名规则并不适合构造器

    默认构造器:

      也叫无参构造器,作用就是创建一个默认对象,如果你不是手写出来,编译器默认会创建

    有参构造器:

      也就有拥有参数的构造器,一旦写了有参构造器,编译器不会创建默认构造器。可以写多个构造器,也就是方法的重载

    区分重载:

      参数,不能通过返回值区分

    this关键字:

    public class Test1 {
    
        private void add(int i) {
    
        }
        public static void main(String[] args) {
            Test1 a = new Test1();
            Test1 b = new Test1();
            a.add(1);
            b.add(2);
        }
    }

    对象a,b都调用了add(),为了区分,编译器把这个对象的引用作为第一个参数传递给add(),就变成了

    Test1.add(a, 1)

    这是内部的表现形式,你并不能直接这样写,无法通过编译

      this关键字只能在方法内部使用,可以用来获取当前对象(调用当前方法的对象)的引用,所以可以把this理解为一般的对象引用,当前方法

    的this会自动应用同一个类的其他方法,所以在一个方法中调用另一个方法不需要使用this,直接调用就可以,可以用,但没必要。

    1、通常可以返回当前对象的引用

    public class Test {
        int i = 0;
        Test increment(){
            i++;
            return this;
        }
    }

    2、可以将当前对象传递给其他方法

    public class Test1 {
    
        public static Test add(Test test) {
            return test;
        }
    }
    public class Test {
        Test add() {
            return Test1.add(this);
        }
    }

    3、构造器互相调用

    在jdk源码中和日常开发中很常见,例如:

    public class ThreadPoolExecutor extends AbstractExecutorService {
       
        public ThreadPoolExecutor(int var1, int var2, long var3, TimeUnit var5, BlockingQueue<Runnable> var6) {
            this(var1, var2, var3, var5, var6, Executors.defaultThreadFactory(), defaultHandler);
        }
    
        public ThreadPoolExecutor(int var1, int var2, long var3, TimeUnit var5, BlockingQueue<Runnable> var6, ThreadFactory var7) {
            this(var1, var2, var3, var5, var6, var7, defaultHandler);
        }
    
        public ThreadPoolExecutor(int var1, int var2, long var3, TimeUnit var5, BlockingQueue<Runnable> var6, RejectedExecutionHandler var7) {
            this(var1, var2, var3, var5, var6, Executors.defaultThreadFactory(), var7);
        }
    
        public ThreadPoolExecutor(int var1, int var2, long var3, TimeUnit var5, BlockingQueue<Runnable> var6, ThreadFactory var7, RejectedExecutionHandler var8) {
            this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
            this.mainLock = new ReentrantLock();
            this.workers = new HashSet();
            this.termination = this.mainLock.newCondition();
            if (var1 >= 0 && var2 > 0 && var2 >= var1 && var3 >= 0L) {
                if (var6 != null && var7 != null && var8 != null) {
                    this.corePoolSize = var1;
                    this.maximumPoolSize = var2;
                    this.workQueue = var6;
                    this.keepAliveTime = var5.toNanos(var3);
                    this.threadFactory = var7;
                    this.handler = var8;
                } else {
                    throw new NullPointerException();
                }
            } else {
                throw new IllegalArgumentException();
            }
        }
        
    }

    PS:this只能调用一个构造器,不能写多个,而且要放在方法第一行,和super很像

    4、区分参数和成员变量的名称

    public Test(int i, String s) {
            this.i = i;
            this.s = s;
        }

    static method只能调用static,反过来倒是可以。this属于对象的,所以不能在static使用

    构造器初始化:

      变量定义的先后顺序决定了初始化顺序。即使随便分布,还是在构造方法之前调用

    public class Test1 {
    
        public Test1(int i) {
            System.out.println("Test1: " + i);
        }
    }
    public class Test {
    
        Test1 test1 = new Test1(1);
    
        Test() {
            System.out.println("Test");
            test3 = new Test1(4);
        }
        Test1 test2 = new Test1(2);
        void  add() {
            System.out.println("add");
        }
        Test1 test3 = new Test1(3);
    
        public static void main(String[] args) {
            Test test = new Test();
            test.add();
        }
    }

     结果:

    Test1: 1
    Test1: 2
    Test1: 3
    Test
    Test1: 4
    add

    静态数据初始化:

      无论创建多少对象,和静态数据没关系,始终只占用一份存储空间

    public class Bowl {
        Bowl(int marker) {
            System.out.println("Bowl: " + marker);
        }
    
        void fl(int marker) {
            System.out.println("fl: " + marker);
        }
    }
    public class Table {
    
        static Bowl bowl1 = new Bowl(1);
        Table() {
            System.out.println("Table()");
            bowl2.fl(2);
        }
        void f2(int marker) {
            System.out.println("f2: " + marker);
        }
        static Bowl bowl2 = new Bowl(2);
    }
    public class Cupboard {
    
        Bowl bowl3 = new Bowl(3);
        static Bowl bowl4 = new Bowl(4);
        Cupboard() {
            System.out.println("Cupboard()");
            bowl4.fl(3);
        }
        void f3(int marker) {
            System.out.println("f3: " + marker);
        }
        static Bowl bowl5 = new Bowl(5);
    }
    public class Test {
    
        public static void main(String[] args) {
            System.out.println("Create new Cupboard() in main");
            new Cupboard();
            System.out.println("Create new Cupboard() in main");
            new Cupboard();
            table.f2(1);
            cupboard.f3(1);
        }
    
        static Table table = new Table();
        static Cupboard cupboard = new Cupboard();
    }

    结果:

    Bowl: 1
    Bowl: 2
    Table()
    fl: 2
    Bowl: 4
    Bowl: 5
    Bowl: 3
    Cupboard()
    fl: 3
    Create new Cupboard() in main
    Bowl: 3
    Cupboard()
    fl: 3
    Create new Cupboard() in main
    Bowl: 3
    Cupboard()
    fl: 3
    f2: 1
    f3: 1

    初始化的顺序: 

      1、父类的静态变量赋值

      2、自身的静态变量赋值

      3、父类成员变量赋值和父类块赋值

      4、父类构造函数赋值

      5、自身成员变量赋值和自身块赋值

      6、自身构造函数赋值

    PS:

      1、静态变量只有在第一次对象被创建(第一次访问静态数据)的时候,才会被初始化,而且只有这一次

      2、构造器是静态方法,即使没有显式地使用static关键字

    显式的静态初始化:

    public class Cup {
    
        Cup(int marker) {
            System.out.println("Cup: " + marker);
        }
    
        void f(int marker) {
            System.out.println("f: " + marker);
        }
    }
    public class Cups {
    
        static Cup cup1;
        static Cup cup2;
        static {
            cup1 = new Cup(1);
            cup2 = new Cup(2);
        }
    
        Cups() {
            System.out.println("Cups()");
        }
    }
    public static void main(String[] args) {
            System.out.println("Inside main()");
            Cups.cup1.f(99);
        }
    static Cups cups1 = new Cups();

    结果:

    Cup: 1
    Cup: 2
    Cups()
    Inside main()
    f: 99

    PS:再一次证明,静态初始化只会执行一次

    再举个栗子,来自于:https://mp.weixin.qq.com/s/HvElZRVf_iFAh24cwuFu-Q

    public class StaticTest {
        public static void main(String[] args)
        {
            staticFunction();
        }
    
        static StaticTest st = new StaticTest();
    
        static
        {
            System.out.println("1");
        }
    
        {
            System.out.println("2");
        }
    
        StaticTest()
        {
            System.out.println("3");
            System.out.println("a="+a+",b="+b);
        }
    
        public static void staticFunction(){
            System.out.println("4");
        }
    
        int a=110;
        static int b =112;
    }

    结果:

    2
    3
    a=110,b=0
    1
    4

    结果有点出人意料:实例初始化竟然在类初始化前面

    类加载过程:

    1、准备:

      为类变量分配内存并设置默认值,因此类变量st为null、b为0。

    PS:

      如果这里b被final修饰,编译时javac将会为value生成ConstantValue属性,在准备阶段虚拟机就会根据ConstantValue的设置将变量设置为

    指定的值。

    例如:

      static final int b=112,那么在准备阶段b的值就是112,而不再是0了。

    初始化:

      就是执行类构造器,类构造器是编译器收集所有静态语句块和类变量的赋值语句,此时会执行:static StaticTest st = new StaticTest();

    冷知识点:

      嵌套初始化时有一个特别的逻辑。内嵌的这个变量恰好是个静态成员,而且是本类的实例。

      就会导致:"实例初始化竟然出现在静态初始化之前"。

    我们在前面已经试验过,如果static StaticTest st = new StaticTest()中StaticTest不是本类,就不会产生这个现象的

  • 相关阅读:
    Flask正则路由,异常捕获和请求钩子
    Flask的路由,视图和相关配置
    Flask搭建虚拟环境
    Flask框架简介
    Django的类视图和中间件
    Django中的cookies和session
    Django请求与响应
    第6章 服务模式 Service Interface(服务接口)
    第6章 服务模式
    第5章分布式系统模式 Singleton
  • 原文地址:https://www.cnblogs.com/huigelaile/p/10998798.html
Copyright © 2011-2022 走看看