用构造器确保初始化
通过构造器,可以确保每个对象都会得到初始化
创建对象时,如果他的类有构造器,JAVA会在操作对象之前自动调用相应的构造器,从而保证初始化的进行
构造器的名称必须与类名完全相同,不接受任何参数的构造器叫做默认构造器(无参构造器)
class Rock2{
Rock2(int i){
System.out.println("Rock:" + i);
}
}
有构造器形式参数,就可以在初始化对象时提供实际参数,初始化和创建时捆绑在一起的,二者不能分离
假设要创建一个类,既可以用标准方式进行初始化,也可以从文件中读取信息来进行初始化。这就需要两个构造器,一个默认构造器,另一个取字符串作为形式参数,字符串表示初始化对象所需要的文件名称。
为了让方法名相同而形式参数不同的构造器同时存在,必须用到方法重载
如果写的类中没有构造器,编译器会自动帮忙创建一个默认构造器
区分重载的方法
每个重载的方法都必须有一个独一无二的参数类型列表,甚至参数类型顺序不同也足以区分两个方法
基本类型的重载
基本类型可以从一个“较小”的类型自动转换为一个“较大”的类型
如果输入的数据类型(实际参数类型)小于方法中声明的形式参数类型,实际的数据类型会被提升,但是char类型不同,如果没有恰好接受参数的方法,就会把char类型直接提升为int型
This关键字
public class ThisDemo {
void f(){
System.out.println(this);
}
public static void main(String[] args) {
ThisDemo demo = new ThisDemo();
demo.f();//此时demo就是调用f()的那个对象(实例)
System.out.println(demo);
}
}
需要明确指出对当前对象的引用时,需要用到this关键字
在返回对当前对象的引用时
public class Leaf {
int i = 0;
Leaf increment(){
i ++;
return this;
}
void print(){
System.out.println(i);
}
public static void main(String[] args) {
Leaf l = new Leaf();
l.increment().increment().increment().increment().print();
}
}
class Person{
public void eat(Apple apple){
Apple peeled = apple.getpeeled();
System.out.println("好吃");
}
}
class Peeler{
static Apple peel(Apple apple){
return apple;
}
}
class Apple{
Apple getpeeled(){
return Peeler.peel(this);
}
}
public class PassTest {
public static void main(String[] args) {
new Person().eat(new Apple());
}
}
尽管可以用this可以调用一个构造器,但是不能调用两个,并且必须要将构造器调用置于最起始处
public class Flower {
int petalCount = 0;
String s ="initial value";
Flower(int petals){//在构造器Flower(String s ,int petals)中被调用
petalCount = petals;
System.out.println(petalCount);
}
Flower(String ss){
System.out.println(ss);
s = ss;
}
Flower(String s ,int petals){
this(petals);//调用构造器Flower(int petals)
this.s= s;
System.out.println("String & int args");
}
Flower(){
this("hi",47);//调用构造器Flower(String s ,int petals)
System.out.println("default constructor(no args)");
}
void printPetalCount(){
System.out.println("PetalCount = " + petalCount + "s = " +s);
}
public static void main(String[] args) {
Flower f = new Flower();
f.printPetalCount();
}
}
static
在static方法内部不能调用非静态方法,反过来可以,而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法
static变量在加载到虚拟机的时候就已经被初始化
static变量初始化先于普通变量
static变量只会初始化一次,和创建的实例没有关系
成员初始化
指定初始化
如果想为某个变量赋值,可以在定义类成员变量的地方为其赋值
public class InitialValues{
boolean bool = true;
char ch = 'x';
byte b = 2;
short s = 0xff;
int i = 999;
long l = 100000;
float f = 1.2f;
double d = 3.14159d;
}
如果是一个类,可以创建一个实例并初始化
class Depth{
}
public class Demo{
Depth De = new Depth();
}
也可以通过调用某个方法来提供初值
public class MethodInit{
int i = f();
int f(){
return 1;
}
}
public class MethodInit2{
int i = f();
int j = g(i);
int f(){
return 1;
}
int g(int n){
return n * 10;
}
}
构造器初始化
在运行时刻,可以调用方法或执行某些动作来确定初值,但是无法组织自动初始化的进行,它在构造器被调用之前使用
public class Counter{
int i;
Count (){
i = 1;
}
}
初始化顺序
在类的内部,变量定义的先后顺序 决定了初始化的顺序,即使变量定义散布于方法定义之间,他们仍会在任何方法包括构造器被调用之前得到初始化
静态数据的初始化
无论创建多少个对象,静态对象都只占用一份存储空间,并且,static关键字不能用于局部变量中,只能作用于“域”(说到域的时候指的就是成员变量)
初始的顺序是先静态对象,而后是非静态对象。
class对象只会加载一次,static域在加载的时候执行(即只执行一次)
class Meat{
Meat(String str){
sout("Meat Constructor " + str);
}
}
public class Dog{
static Meat meat = new Meat("static");
static void doSth(){
sout("Dog Static Method " + meat);
Dog(){
sout("Dog constructor excute ..")
}
private static void main (String[] args){
//new Dog();总结1-1,首次创建Dog实例,构造器会去执行
//sout("Dog.meat");总结1-2,Dog中的静态域首次访问的时候去找Dog.class,意味着静态域会被初始化
//Dog.doSth();总结1-3,Dog中的静态域首次访问的时候会去找Dog.class,意味着静态域会被初始化
//总结2,静态域只在Dog.class对象加载到虚拟机的时候执行一次
new Dog();//总结3,new Dog();分配存储空间,意味着初始化一个Dog实例,构造器将会执行
//sout(instance.m)总结4,5 对Dog中成员变量的区域清零,即普通的成员便令m将为null
//总结6,执行构造器,确保初始化
}
}
}
数组初始化
枚举
枚举类型的构造器是私有的