Java面向对象-构造函数,函数重载,this,static

构造函数

构造函数存在的意义是在对象初始化时进行属性的赋值操作

  • 名称必须和类名完全一致
  • 没有返回值
  • 没有为类创建显式的构造函数时,JVM会自动生成一个不带参数的构造函数,且在该函数中什么都不做
  • 显式创建构造函数后,JVM就不会自动生成不带参数的构造函数
public class Dog{

    private int age;
    private String name;

    public Dog(){
        name = "狗狗";
        age = 10;
    }

    public void info(){
        int age = 20;
        System.out.println(name+"今年"+age+"岁");
    }
}
函数重载
  • 函数的名称一致,但参数(类型、个数、顺序)不一致
  • 参数名形参不同时不构成函数重载
  • 函数返回值不同时也不构成函数重载
public class Animal {
    public static void main(String[] args) {
        Dog dog = new Dog("臭臭",10);

        dog.info();
        dog.bite();
    }
}
class Dog{

    private int age;
    private String name;
		
    public Dog(String name,int age){
        name = name;
        age = age;
        System.out.println(name);
    }

    public void info(){
        System.out.println(name+"今年"+age+"岁");
    }

    public void bite(){
        System.out.println(name+"咬了人");
    }
}
输出:
  臭臭
	null今年0null咬了人

来分析下两个问题

  • Dog dog = new Dog("臭臭",10); 这句创建了几个变量?
  • 构造函数中的赋值会不会有问题

在这里插入图片描述

Dog dog = new Dog("臭臭",10); 这句创建了几个变量:

  1. 创建了一个dog变量,指向堆中的内存,内存里有初始化赋值的age和name
  2. 创建了name=臭臭变量
  3. 创建了age=10的变量

一共是创建了3个对象

构造函数中的赋值会不会有问题? 会

public Dog(String name,int age){
	name = name;
	age = age;
}

jvm先在栈中找name,如上图,name=臭臭在栈里是有的,形参的name被赋值给了栈里的name,此时name输出是 臭臭,但其实我们是想让dog中的name属性被赋值的,这样以后调用info(),bite()才有意义,那么怎么才能赋值呢?jvm中this指针解决了这一问题

this指针

在每个对象的内部都有一个this指针指向自己

注意如何正确使用this指针

  • this是一个关键字,是一个引用,是一个变量,保存内存地址指向本身
  • this可以使用在实例方法中,也可以使用在构造方法中
  • this不能使用在静态方法中。this在实例方法中相当于谁调用这个实例方法,this就是谁,但静态方法是类级别方法,不存在当前对象,所以this不能使用在静态方法中。
  • this大部分情况下可以省了,但如果用于区分局部变量和实例变量时不能省略
  • this()语句只能出现在构造方法的第一行,表示当前构造方法调用本类其他的构造方法,增强代码复用

在这里插入图片描述

我们将代码修改为:

public Dog(String name,int age){
	this.name = name;
	this.age = age;
}

这样就赋值到了Dog对象上的变量

对象的初始化顺序
  1. 先按顺序初始化属性
  2. 构造函数的初始化
public class Animal {

    public static void main(String[] args) {
        Dog dog = new Dog("臭臭");
    }
}
class Dog{

    Color color1 = new Color("白色");

    public Dog(String name){
        System.out.println("狗狗的名字:"+name);
    }

    Color color2 = new Color("斑点");
}
class Color{
    public Color(String color){
        System.out.println("颜色:"+color);
    }
}
输出:
  颜色:白色
	颜色:斑点
	狗狗的名字:臭臭
static

使用范围: java static 关键字可以用在变量、方法、代码块和嵌套类

作用范围:static关键字属于类的,使用static修饰的属性或方法,建议使用类名调用

初始化: static被JVM先初始化

static修饰后,为什么不能使用实例的变量、成员或者其他数据:

因为在JVM初始化时,static被先初始化,如果在static修饰的代码中有调用实例,那实例尚未分配空间。

静态(static)修饰如下:

  1. 变量:称为类变量、静态变量
  2. 方法:称为类方法、静态方法
  3. 代码块:称为静态代码块
  4. 嵌套类:称为静态内部类
静态变量

类的成员变量可以分为以下两种:

静态变量(或称为类变量),指被 static 修饰的成员变量。

实例变量,指没有被 static 修饰的成员变量。

静态变量与实例变量的区别

1)静态变量

运行时,Java 虚拟机只为静态变量分配一次内存,加载类过程中完成静态变量的内存分配。

在类的内部,可以在任何方法内直接访问静态变量。

在其他类中,可以通过类名访问该类中的静态变量。

2)实例变量

每创建一个实例,Java 虚拟机就会为实例变量分配一次内存。

在类的内部,可以在非静态方法中直接访问实例变量。

在本类的静态方法或其他类中则需要通过类的实例对象进行访问。

静态变量在类中的作用:

静态变量可以被类的所有实例共享,因此静态变量可以作为实例之间的共享数据,增加实例之间的交互性。

如果类的所有实例都包含一个相同的常量属性,则可以把这个属性定义为静态常量类型,从而节省内存空间。例

如,在类中定义一个静态常量 PI,System.out.println()

public class Animal {

    public static void main(String[] args) {
        Dog dog1 = new Dog();
        dog1.name = "John";
        Dog.age = 1;
        Dog dog2 = new Dog();
        dog2.name = "melon";
        Dog.age = 2;
        System.out.println(dog1.name+ " "+dog1.age);
        System.out.println(dog2.name+" "+dog2.age);
    }
}
class Dog{
    String name;
    static int age;
}

输出:
  John 2
  melon 2

static内存模型如下:

在这里插入图片描述

静态方法

同成员变量,成员方法也可以分为以下两种:

静态方法(或称为类方法),指被 static 修饰的成员方法。

实例方法,指没有被 static 修饰的成员方法。

静态方法与实例方法的区别:

静态方法,属于类,而不属于类的对象。

1)它通过类直接被调用,无需创建类的对象。

2)静态方法中,不能使用 this 关键字,也不能直接访问所属类的实例变量和实例方法;

3)静态方法中,可以直接访问所属类的静态变量和静态方法。

4)同this 关键字,super 关键字也与类的实例相关,静态方法中不能使用 super 关键字。

实例方法,可直接访问所属类的静态变量、静态方法、实例变量和实例方法。

静态方法与静态变量好处

  1. 属于类级别,无需创建对象就即可直接使用,使用方便。

  2. 全局唯一,内存中唯一,静态变量可以唯一标识某些状态。

  3. 类加载时候初始化,常驻在内存,调用快捷方便。

静态方法与静态变量缺点:

  1. 静态方法不能调用非静态的方法和变量。

  2. 不能使用this和super关键字。

静态方法与静态变量适用场景

  1. 静态方法,最适合工具类中方法的定义;比如文件操作,日期处理方法等。

  2. 静态方法,适合入口方法定义;比如单例模式,因从外部拿不到构造函数,所以定义一个静态的方法获取对象非常有必要。

  3. 静态变量适合全局变量的定义;举例:用一个布尔型静态成员变量做控制标志。

静态代码块

定义:静态代码块,是 Java 类中的 static{ } 修饰的代码。

作用:用于类初始化时,为类的静态变量赋初始值,提升程序性能。

静态代码块的特点:

静态代码块,有点类似于一个方法,但不可以存在于任何方法体内。

静态代码块,可以置于类中的任何地方,类中可以有多个静态初始化块。

Java 虚拟机在加载类时执行,将只需要进行一次初始化的操作放在 static 代码块。

类中含多个静态代码块,Java虚拟机将按它们在类中出现的顺序依次执行,且都执行一次。

同静态代码块与静态,不能直接访问类的实例变量和实例方法,需通过类的对象访问。

静态类

java中一个类要被声明为static的,只有一种情况,就是静态内部类(内嵌类)。如在外部类声明为static的,程序编译都不会通过。

1、静态内部类,跟静态方法一样,只能访问静态成员变量和方法,不能访问非静态方法和属性。

2、普通内部类,可以访问任意外部类的成员变量和方法。

3、静态内部类,可以声明普通成员变量和方法,而普通内部类不能声明static成员变量和方法。

4、静态内部类,可以单独初始化。

适用场景:当外部类需要使用内部类,而内部类无需外部类资源,并且内部类可以单独创建时,考虑采用静态内部类的设计,在知道如何初始化静态内部类。

静态内部类,调用外部类的构造函数来构造外部类;静态内部类可被单独初始化

静态类总结:

1.如果类的构造器或静态工厂中有多个参数,设计这样类时,最好使用Builder模式,特别是当大多数参数都是可选的时候。

2.如果现在不能确定参数的个数,最好一开始就使用构建器即Builder模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值