Java构造函数(笔记11)

Java构造函数

一、构造函数

特点:
//构造函数是多个,在new对象调用的时候匹配上哪个,则调用哪个
1) 在类对象创建的时候执行,而且只执行一次
2) 和类名相同
3) 没有返回值, 连void也不行
public class Japan {
void Japan() { //这个不是构造函数,虽然它编译不报错
}
}
4) 不能手工调用
5) 可以重载,不可以重写
6) 如果设计一个类的时候,没有设计构造函数,则它会生成一个默认的,无参的空构造函数
7) 如果自已定义了一个构造函数,则系统就不再生成默认的构造函数了
8) 最主要的作用,是用来对类对象进行初始化
//举例说明
public class Japan {
Japan(){ //系统默认的
System.out.println("无参的构造函数被调用了");
}
Japan(String msg){
System.out.println("这是我的主人让我说的话:"+msg);
}
int age;
String name;
String country;
void speak(){
System.out.println("北海道是中国领土");
}
}

class Test{
public static void main(String[] args) {
Japan japan=new Japan(); //调用无参的构造函数
Japan japan2=new Japan("这是传入的参数"); //调用带参的构造函数
}
}
 
//例子,使用构造函数传参
//通过构造函数来解决参数的初始化问题
public class TV {
private int width;
private int height;
private String pinpai; //品牌
private String color; //颜色
TV(int width,int height,String pinpai,String color){
this.width=width; //this指向类对象,前面的this.width指是类对象中的width,后面的width是参数,this起到一个类似指针的作用,以作区分
this.height=height;
this.pinpai=pinpai;
this.color=color;
}
void turnOn(){
System.out.println(pinpai+"牌电视开了");
}
void turnOff(){
System.out.println("电视冒烟了,烟是"+color+"色的");
}
void play(){
System.out.println("武打片");
}
void show(){
System.out.println("这台电视:");
System.out.println("体积:" +width*height);
System.out.println("品牌:" +pinpai);
System.out.println("颜色:" +color);
}
}

class Test2{
public static void main(String[] args) {
TV tv=new TV(200,150,"熊猫","银灰");
tv.show();
tv.turnOn();
tv.play();
tv.turnOff();
}
}

二、this关键字

this可以调用本类的属性,方法
例如:
TV(String pinpai,String color){
this.pinpai=pinpai;   //this指向类对象,前面的this.pinpai指是类对象中的pinpai,后面的pinpai是参数,this起到一个类似指针的作用,以作区分
this.color=color;  //使用this 调用本类的属性
this.turnOn();  //使用this调用本类的方法
....
}
  
//使用this(参数列表) 可以在一个构造函数中调用本类的另一个构造函数
TV(int width,int height,String pinpai,String color){
this(pinpai, color);  //用this调用其他的构造函数,而且必须放在第一句,调用格式是this加括号直接传参
this.width=width;
this.height=height;
}

三、对象作为参数传递

1) 基本数据类型做为函数的参数
public static void main(String[] args) {
int score=59;
change(score);
System.out.println(score); // 59 ,可以看到,对于基本数据类型,做为函数的参数,对形参的改变,不会影响到实参,因为它不共用堆内存对象,是两个栈内存
}

static void change(int score){ //函数的形参,可以视为局部变最 local 
score=90;
}

2) 引用类型做为对象的参数 
public class Test3 {
public static void main(String[] args) {
Student stu=new Student();
stu.score=59;
change(stu);
System.out.println(stu.score); //90   
}
static void change(Student stu){  //当引用类型做为函数的参数的时候,对形参的改变,会影响到实参,因为共用堆内存对象,改变堆内存会影响..
stu.score=90;
}
}

class Student{
int score;
}

四、static关键字

static 是静态的意思
//例一 需求:统计Cat类的实例一共创建了多少
public class Cat {
Cat(){
count++;
}
static int count;  //用来统计本类的实例创建了多少个
int age;
String name;
}

class Test5{
public static void main(String[] args) {
Cat c1=new Cat();
Cat c2=new Cat();
Cat c3=new Cat();
Cat c4=new Cat();
System.out.println(c4.count);  //4
System.out.println(c1.count);  //4
}
}
static 关键字的特点
1) 多个对象,共享同一份数据  (附:java中没有全局变量,有这种需求的时候,可以使用static关键字实现)
2) 它修饰的成员,在类加载的时候加载,并初始化,只初始化一次
3) 它可以修饰属性或方法,被它修饰的成员,可以直接用类名. (推荐) 引用,也可以用对象名. 引用, 静态成员,可以脱离对象而存在
4) 无法从静态上下文中访问非静态上下文( 在静态方法中,不可能出现this关键字 )
//例子 在实例方法中,访问了静态成员
public class Cat {
static String home="中国";
int age;
String name;
//实例方法
void talk(){
System.out.println("我的家在:"+home);  //在实例方法中,访问静态成员,OK
System.out.println("我的年龄:"+age);
System.out.println("我的名字"+name);
}
}

class Test5{
public static void main(String[] args) {
Cat c=new Cat();
c.talk();
}
}

//例子,在静态上下文中,无法访问非带态上下文 (上下文: 函数,或字段)
class Cat {
static String home="中国";
int age;
String name;

//实例方法
void talk(){
System.out.println("我的家在:"+home);  //ok 在实例方法中,访问静态成员,OK
System.out.println("我的年龄:"+age);
System.out.println("我的名字"+name);
}
    
//试图在静态方法中,访问非静态成员,出错
static void speak(){
System.out.println("我的名字是:"+age);  //错误 Cannot make a static reference to the non-static field name
}
}
     
     附: public static void main(String[] args) 
     -- public 表示这个函数是公共的
      -- static 表示这个函数是静态的
      -- void 表示这个函数没有返回值
      -- main 是一个固定的名称
      -- String[] 表示函数接收一个数组类型的参数
      -- args 参数名称
   
例子 给main函数传参:
class Test{
public static void main(String [] args){
for(int i=0;i<args.length;i++){
System.out.println(args[i]);  //取出传给main函数的参数
}
}
}
运行的时候 java Test 参数1 参数2 ....

五、构造代码块和静态代码块

//例子 
class Sheep{
{ //构造代码块,执行早于构造函数,在对象每次创建的时候,都执行
System.out.println("构造代码块");
}
Sheep(){ //构造函数
System.out.println("构造函数");
}
static {
System.out.println("这是静态代码块");
}
}

//例子
class Test6{
public static void main(String[] args) {
Sheep sheep1=new Sheep();
Sheep sheep2=new Sheep();
}

//这是静态代码块
//构造代码块
//构造函数

//构造代码块
//构造函数
}


//例子 下面程序输出的结果
public static void main(String[] args) {
new Person(9999);
new Person();
}
    
class Person{
Person(){
System.out.println("a");
}
Person(int x){
System.out.println(x);
}
static{   //静态成员只初始化一次
System.out.println("b");
}
{
System.out.println("c");
}
}
//b c 9999 c a

六、类的加载和执行顺序

Cat cat=new Cat(); 
 
  1) 先将Cat.class这个字节码文件,装载到内存中
  2) 静态成员先初始化 (静态属性,静态代码块)
  3) 在堆内存上开辟空间, 类成员默认初始化
  4) 类成员显式初始化
  5) 构造代码块执行
  6) 构造函数执行
  7) 将栈内存中的引用指向堆内存中的实体


    //下面的两个静态成员,谁先初始化?谁写在前面,谁先初始化
    class cat{
    int age=90;
    int weight=15;
    String nickName="tom";
    static String home="赵明明家"  //静态属性
    static { //静态代码块
    System.out.println("喵~~");
    }
    }

猜你喜欢

转载自blog.csdn.net/weixin_41205479/article/details/80030133