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不是本类,就不会产生这个现象的
Java基础(二)--this关键字及初始化的更多相关文章
- Java基础(二)-static关键字分析
static关键字是我们在编程中经常会使用到的,但有些可能只知其然而不知其所以然.下面介绍static关键字的作用再通过例子结合说明. static关键字共有五种作用(先说明static所修饰的不会改 ...
- Java基础-标识符与关键字
Java基础-标识符与关键字 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是标识符 标识符就是程序员在编写程序时,给类,变量,方法等起的名字. 二.标识符的命名规则 1& ...
- Java面试题总结之Java基础(二)
Java面试题总结之Java基础(二) 1.写clone()方法时,通常都有一行代码,是什么? 答:super.clone(),他负责产生正确大小的空间,并逐位复制. 2.GC 是什么? 为什么要有G ...
- Java入土--Java基础(二)
Java基础(二) 接上一讲,我们接着来聊聊Java的一些基础知识,下一讲就会进行流程的控制. 类型转换 首先呢,是类型的转换,接上一个内容的数据类型,类型转换就是数据类型更进一步的应用. 由于Jav ...
- Java基础语法(1)-关键字与保留字
title: Java基础语法(1)-关键字与保留字 blog: CSDN data: Java学习路线及视频 1.关键字 关键字(keyword)的定义和特点 定义:被Java语言赋予了特殊含义,用 ...
- Java基础系列--static关键字
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/8477914.html 一.概述 static关键字是Java诸多关键字中较常使用的一个,从 ...
- Java基础(五) final关键字浅析
前面在讲解String时提到了final关键字,本文将对final关键字进行解析. static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提 ...
- Java基础(三)-final关键字分析
今天来谈谈final关键字的作用, 虽然有很多博文关于final进行了很深的研究,但还是要去记录下谈谈自己的见解加深下印象.下面直接进入主题: 一.final关键字的作用 1.被final修饰的类不能 ...
- java基础(二)-----java的三大特性之继承
在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...
随机推荐
- 使用Node搭建reactSSR服务端渲染架构
如题:本文所讲架构主要用到技术栈有:Node, Express, React, Mobx, webpack4, ES6, ES7, axios, ejs, log4js, scss,echarts, ...
- 动态生成页面(一)——ASP.NET中Literal使用
在页面中加入内容时,假设是静态内容.无需使用容器,能够直接将标记作为HTML直接加入到页面中:可是,假设是动态内容,则必须借助容器将内容加入到页面中.典型的容器有:Label控件.Literal控件. ...
- ZOJ Design the city LCA转RMQ
Design the city Time Limit: 1 Second Memory Limit: 32768 KB Cerror is the mayor of city HangZho ...
- JBOSS和EJB学习一
1.使用软件 IDE:Eclipse4.3(开普勒) EE版本 服务器:jboss EAP 6.2 eclipse-jboss plugin:jbosstools-Update-4.1.2.Final ...
- ios22--动画
控制器: // // ViewController.m // 07-渐变动画 // // Created by xiaomage on 15/12/30. // Copyright © 2015年 小 ...
- Java文件实时监控Commons-io
今天看到一网友写的 Java 文件监控,实时监控文件加载 ,突然想到Commons-io中已有此功能的实现,先温习下 写个简单的Demo: 有三种方式: 1.java common.io 内部实 ...
- python re正则表达式模块
模块的的作用主要是用于字符串和文本处理,查找,搜索,替换等 复习一下基本的正则表达式吧 .:匹配除了换行符以为的任意单个字符 *:匹配任意字符,一个,零个,多个都能匹配得到 俗称贪婪模式 +:匹配 ...
- Android 属性系统 Property service 设定分析 (转载)
转自:http://blog.csdn.net/andyhuabing/article/details/7381879 Android 属性系统 Property service 设定分析 在Wind ...
- bzoj 1673: [Usaco2005 Dec]Scales 天平【dfs】
真是神奇 根据斐波那契数列,这个a[i]<=c的最大的i<=45,所以直接搜索即可 #include<iostream> #include<cstdio> usin ...
- bzoj 1778: [Usaco2010 Hol]Dotp 驱逐猪猡【dp+高斯消元】
算是比较经典的高斯消元应用了 设f[i]为i点答案,那么dp转移为f[u]=Σf[v]*(1-p/q)/d[v],意思是在u点爆炸可以从与u相连的v点转移过来 然后因为所有f都是未知数,高斯消元即可( ...