构造方法
构造方法:创建对象,给对象中的成员进行初始化
格式:
1.方法名与类名相同
2.没有返回值类型,连void都没有
3.没有具体的返回值
public Student() {}
构造方法的重载
1.如果我们没有给出构造方法,系统将自动提供一个无参构造方法。
2.如果我们给出了有参数构造方法,系统将不再提供默认的无参构造方法。
注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法
public Student(String name, int age, String number) {
this.name = name;
this.age = age;
this.number = number;
}
/*
因为已经给出了含有三个参数的构造方法
public Student(){}这个默认构造方法就不存在了
Student s=new Student();这句话将无法执行,因为无法创建无参的对象
所以我们要自己给出无参构造方法
*/
public Student() {}
public Student(String name, int age, String number)
{
this.name = name;
this.age = age;
this.number = number;
}
static(静态)
如果我们有一个共享数据,比如国籍,在一个国家或者地区的服务器中,国籍都是相同的
如果每一个对象中都存一份国籍很占内存,所以我们可以将国籍这个属性提取出来,使其只存一份,并使其共享,这时就要使用static关键字
被static修饰的成员变量或者成员方法存放在方法区的静态区中
static是一个修饰符,用于修饰成员(成员变量、成员函数)。
当成员被静态修饰后,就多了一种调用方式,除了可以被对象调用外,还可直接被类名调用(类名.静态成员)
class Person
{
static String country="CN";
}
class PersonDemo
{
public static void main(String[] args)
{
Person p=new Person();
System.out.println(p.country); //这两句的输出结果都是"CN"
System.out.println(Person.country);
}
特有内容随着对象存储,而共有的数据可以用static修饰
方法区(共享区、数据区):存储类中的方法和共享数据
static的特点:
1.随着类的加载而加载 当类加载到内存中,静态成员以及值也加载到内存中,也就是说,静态成员会随着类的消失而消失,他的生命周期最长
2.优先于对象存在
3.被所有对象所共享
4.可以被类名所调用
被静态修饰的成员变量被称为静态成员变量或者叫类变量
没有被静态修饰的成员变量被称为成员变量或者叫实例变量
实例变量和类变量的区别
1.存放位置
类变量随着类的加载存在于方法区中
实例变量随着对象的建立存在于堆内存中
2.生命周期
类变量生命周期最长,随着类的消失而消失
实例变量生命周期随着对象的消失而消失
静态使用的注意事项
1.静态方法只能访问静态成员,非静态方法既可以访问静态也可以访非静态
非静态成员随着对象的创建而存在,静态方法优先于非静态存在,所以不可以调用未存在的方法和变量。而当非静态存在时,静态已经存在
2.静态方法中不可以定义this,super关键字
因为静态优先于对象存在,所以静态方法中不可以出现this关键字
优点:
1.对对象的共享数据进行单独空间的存储,节省堆内存空间,没必要每一个对象中都存储一份数据
2.可以直接被类名调用
缺点:
1.生命周期过长,占用内存
2.访问出现局限性,静态只能访问静态
静态代码块
static
{
要执行的代码;
}
//随着类的加载而执行,只执行一次,且优先于主函数,用于给类进行初始化
class StaticCode
{
static
{
System.out.println('a')
}
}
class StaticCodeDemo
{
public static void main(String[] args)
{
new StaticCode(); //执行该语句打印a
new StaticCode(); //因为类已经存在所以该语句不执行
}
}
class StaticCode
{
StaticCode()
{
System.out.println('b'); //构造函数
}
static
{
System.out.println('a'); //静态代码块
}
{
System.out.println('c'); //代码块
}
StaticCode(int x)
{
System.out.println('d'); //构造函数
}
}
class StaticCodeDemo
{
public static void main(String[] args)
{
new StaticCode(4);
}
}
/*
打印结果:
a
c
d
*/
/*
初始化时,先加载类,静态代码块随着类的加载而执行,
之后代码块随着对象的建立而被执行,最后执行对应的构造函数
*/
对象的初始化过程
Person p=new Person("小明",31);
步骤:
1.因为new用到了Person类,所以会先找到Person.class文件并加载到内存中
2.执行该类中的静态代码块(如果有的话),给Person类进行初始化
3.在堆内存中开辟空间,分配内存地址
4.在堆内存中建立对象的特有属性,并进行默认初始化
5.对属性进行显示初始化
6.对对象进行构造代码块初始化
7.对对象进行对应构造函数的初始化
8.将内存地址赋值给栈内存中的p变量