Java基础复习6—初始化
之前讲过了类的一些基础,想必大家都知道了类的定义
什么?你忘了?
下面给你一个例子快速复习
class AClass{
int a;
boolean b;
void getA(){
return this.a;
}
AClass(){
System.out.println("这是构造函数被调用");
}
}
int a是类的属性
getA()是类的方法
统一使用getName()与setName()方法来对对象的属性进行取与设置的操作
AClass()是类的构造函数,名字与类相同,没有返回值
好了好了,别说了,我已经看够了
那现在上主菜,Java中的初始化
1.指定初始化
获取你是有C++基础的开发者,你一定知道初始化的一个禁忌,直接在类中就地初始化。
Java中最简单的初始化——指定初始化
你哪个变量需要初始化,就直接赋值给他就好了嘛。
如下,直接给赋值。
class AClass{
int a=5;
boolean b=true;
void getA(){
return this.a;
}
AClass(){
System.out.println("这是构造函数被调用");
}
}
那对于非基本类型的对象,怎么办?
简单,对于基础类型,初始化的方法是赋值,对于类?
你已经知道了,使用new关键字
如下
class AClass{
int a=5;
boolean b=true;
AnotherClass c = new AnotherClass();
void getA(){
return this.a;
}
AClass(){
System.out.println("这是构造函数被调用");
}
}
总结一下,指定初始化的方式允许程序员直接给类的成员设置初始值,如果是对象,设置初始值的方式是new
2.构造器初始化
顾名思义,之前我们不是说过有一个构造方法嘛:快速回顾什么是构造方法?
哇,兄弟你又忘了?
我们再来看一波概念:
构造方法解决的问题是:在调用一个类之前,都需要调用initialize()方法。通过调用initialize()方法,我们可以搭建一个构造器,保证所有的对象都会得到初始化。
就是说,new对象会使用对应的构造方法,置于是哪个方法,看你的参数了
那可以初始化一个类,我们顺便把类的属性一起初始化了就行了嘛
直接上例子
class AClass{
int a=5;
boolean b=true;
AnotherClass c = new AnotherClass();
void getA(){
return this.a;
}
//不删除他的原因是为了不给参数也能生成对象
AClass(){
System.out.println("这是构造函数被调用");
}
//个人习惯使用this,如果你的参数没有与属性名字冲突,可以不用this,
//个人认为使用这种方式更能体现他是个“构造器初始化”
AClass(int a,boolean b,AnotherClass c){
this.a=a;
this.b=b;
//注意这里的对象赋值是引用,实际上没有新建对象,想新建对象就new
this.c=c;
}
}
再在这里提醒一遍:引用与对象是不同的,这里构造器是把引用指向了另一个对象,并没有新建对象!
不过不需要担心这个对象死去导致空指针异常,你已经是一个成熟的Java人了滑稽。
因为Java不允许用户自行回收内存,而这里的引用相当于两个对象直接有了联系,所以AClass对象消失之前,内部对象是不会消失滴!不懂?看之前的文章嘛《让你第一次认识到Java的内存管理》
3.静态数据的初始化
静态,静态,静态是什么意思?
你可以幻想自己在Java的虚拟机之中,每个对象都有自己的空间,存了属于对象自己的数据,这叫动态
静态呢?刚好相反,静态的是数据是类共享的,只占用了一份存储区域。
静态是指共享,一份,而并不是最终,所以我们仍可以修改静态参数,但是这是很不推荐的行为,毕竟是公家的数据,你一个对象修改了,别不就遭了,同时也有大佬遇到了利用静态的原理反而翻车的情况——分布式。
静态数据初始化没什么特殊的,与非静态相同。
class AClass{
static int a=5;
boolean b=true;
static AnotherClass c = new AnotherClass();
void getA(){
return this.a;
}
AClass(){
System.out.println("这是构造函数被调用");
}
}
哇,每次都要写static,好累啊
恭喜你,Java还真的有解决这个的方案
用一个例子,直接说明,这叫显示静态初始化
class AClass{
boolean b=true;
static{
int a=5;
AnotherClass c = new AnotherClass();
}
void getA(){
return this.a;
}
AClass(){
System.out.println("这是构造函数被调用");
}
}
这非静态的就不服了,你们静态可以,我们非静态也可以,诶确实,真的可以
这就是实例初始化
class AClass{
boolean b=true;
{
int a=5;
AnotherClass c = new AnotherClass();
}
void getA(){
return this.a;
}
AClass(){
System.out.println("这是构造函数被调用");
}
}
4.那初始化的顺序呢?
综合上面的讲述,我们有构造器初始化,静态,直接初始化这三种情况
讲顺序之前,请先回顾一下静态属性的位置
哦,你应该知道了,静态属性的只有一个,归属于类。
那肯定静态是排第一嘛!
老二是谁嘞,我们思考一下,构造方法有多种,所以会不会用到全部初始化的构造方法还不一定,那一定会用到的是谁嘞,直接初始化!
好的直接初始化排老二!
最后就是构造方法喽
所以综上,再加点调料,顺序如下:
- 在类被载入时,有关静态初始化的操作会执行(静态初始化只在Class对象首次加载使进行一次),值的一提的是,静态成员只有在使用到的时候才会被初始化(类.名字进行访问&初始化对象)
- 在堆上为对象分配空间
- 存储空间清零,所有数据为默认(安全)
- 执行在字段处定义的初始化操作
- 执行构造器
外传:数组初始化
为什么要单独写数组呢
主要是忘了写
开玩笑开玩笑,数组并不能算一种新的初始化方法(个人认为),他的初始化模式与之前的相似。
在介绍之前,还是先看看什么是数组:
数组:相同类型元素紧密排列。提炼出来差不多就是这样。
比如这个烤羊肉串(我没有诱惑你),羊肉串是类型相同的,然后一个一个排列在一起。
Java怎么实现一个数组?
两种形式
- type[] name; //Java 新增的方式
- type name[];//传统C语言风格
那总要一种推荐的嘛
本人选择type[] name;原因是更有类型的意味,数组在Java中可以算一个特殊的对象了。
如何初始化?
两种
第一个,直接初始化
(有什么奥秘嘛,直接用{}就能初始化)
例子给你了
int[] a1={1,2,3,4};
这里必须要提到,这种方式并没有直接表明数组的长度,个人还是喜欢第二种,不过某些场景还是这种方便
数组越界的问题
C和C++中是默认“允许”数组越界的,程序不会报错,反而能正常运行,不过结果可想而知
Java中,数组越界则会出现RuntimeError(运行时异常),保护程序
第二种,使用new关键字
是不是有类的味道了呢?
int[] a1= new int[5];
另外对于对象数组,必须再次了解一点:引用≠对象
所以当下次你再创建了一个下面的对象数组
ClassName[] b= new ClassName[15];
你还没有给对象数组中的引用赋值就报错了
就再强调一遍,Java初始化对象的办法只有new,所以其他各种莫名其妙的都没有初始化哦,要用其他语言当我没说。
声明了一个对象数组,还需要初始化才能有实际的内容,
小心使得万年船哦。