面向对象
构造函数
- 特点:函数名和类名相同;不同定义返回值类型;没有具体的返回值。
- 作用:给对象进行初始化。
class Person
{
private String name;
private int age;
//定义一个Person类的构造函数
Person()//构造函数,空参数的
{
System.out.println("person run");
}
public void speak()
{
System.out.println(name+":"+age);
}
}
class ConsDemo
{
public static void main(String[] args)
{
Person p = new Person();//构造函数,构建对象时调用的函数,可以给对象进行初始化。
//这里调用了构造函数Person(),所以运行结果为person run。
}
}
- 创建对象都必须通过构造函数初始化。
- 一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数,即Person(){};若定义了指定的构造函数,默认的就会消失。
构造函数和一般函数的区别
- 构造函数:对象创建时,就会调用对应的构造函数,对对象进行初始化。一般函数:对象创建后,需要函数功能时才调用。
- 构造函数:对象创建时,只调用一次。一般函数:对象创建后,可以被调用多次。
- 什么时候定义构造函数?
在描述事物时,事物一存在就具备的一些属性,这些属性就定义在构造函数中。
内存图解
- ①主函数进栈;②堆内创建对象,赋予地址,将对象默认初始化;③调用构造函数将对象初始化;④函数Person(n,a)进栈;⑤函数的值赋给对象,函数弹栈,对象初始化完成;⑥speak()进栈,调用完成,弹栈。
关键字this
this就是所在函数所属对象的引用,可以用来区分重名的成员变量和局部变量。简单说:哪个对象调用了this所在的函数,this就代表哪个对象。
- this.name为成员变量,name为局部变量。
- 一个类中的所有成员想要运行,一定要被对象调用,即this.(只不过大部分情况下省略了)
内存图解
①主函数进栈;② 堆内创建对象,赋予地址,将对象默认初始化;③构造函数Person进栈,对象的地址赋给this;④函数的值赋给对象,函数弹栈,对象初始化完成;⑤speak()进栈,地址赋给this,调用完成,弹栈(speak的this.通常被省略,因为不重名)。
- 构造函数可以直接调用一般函数,反过来则不行。
- 构造函数如何调用构造函数?
Person(String name)
{
this.name=name;
}
Person(String name,int age)
{
this.name=name;//这个地方若直接调用上一个构造函数,则写成this(name),name即参数,构造函数的区分就是通过参数来是别的
this.age=age;
}
注意:构造函数调用其他构造函数,只能定义在构造函数第一行,因为初始化动作要先执行。
应用
判断两个人是否同龄
public boolean compare(Person p)
{
if(this.age==p.age)
return true;
else
return false;
//或者renturn this.age==p.age;
}
Person p1 = new Person("a",20);
Person p2 = new Person("x",13);
p1.compare(p2);//this代表p1,p代表p2
关键字static
特点
- static是一个修饰符,用于修饰成员。
- static优先于对象存在,static随着类的加载就存在了。
- 用static修饰的数据是共享数据,对象中存储的是特有数据。
- 它不仅可以被对象使用,也可以直接被类名访问。
成员变量和静态变量的区别
- **两个变量的生命周期不同。**成员变量随着对象的创建而存在,随着对象的回收而释放;
静态变量随着类的加载而存在,随着类的消失而消失(一般虚拟机结束了,类就消失了)。 - **调用方式不同。**成员变量只能被对象调用;静态变量还可以被类名调用,所以一般推荐用类名调用静态变量,一眼就能看出来区别。
- 成员变量也称为实例变量;静态变量也称为类变量。
- **数据存储位置不同。**成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据;静态变量数据存储在方法区(共享区)的静态区。
注意事项
- 静态方法只能访问静态成员。(非静态可以访问静态,也可以访问非静态)
- 静态方法中不可以使用this和super关键字。(因为static先加载,对象还未存在)
- 主函数main是静态的。
- 主函数如何调用静态函数?
class StaticDemo
{
public static void main(String[] args)
{
show();//报错:静态上下文不能引用非静态
//改成new StaticDemo().show();new一个对象来调用show()
}
public void show()
{
System.out.println("a");
}
}
main函数解析
主函数特殊之处:格式是固定的;被jvm所识别和调用。
-
public:代表权限必须最大
-
static:不需要对象,直接用主函数所属类名调用即可
-
void:主函数没有具体的返回值
-
main:函数名
-
String[] args:主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型
-
内存图解
静态什么时候用
静态变量
当分析对象中所具备的成员变量的值都是相同的,这个成员就可以被静态修饰。
静态函数
只参考一点:函数功能是否有访问到对象中的特有数据。(从代码看,该功能是否需要访问非静态的成员变量,如果不需要,就可以将该功能定义为静态的)
class ConsDemo
{
int age;
static int num = 9;
public static void speak()//访问的是静态变量num,所以定义为静态函数
{
System.out.println(num);
}
public void show()//访问了对象中的特有数据age,所以定义为非静态
{
System.out.println(age);
}
}//对象的创建没有调用特有数据,该对象的创建就没有意义,浪费堆内存。
静态代码块
- 随着类的加载而执行,而且只执行一次。
- 作用:用于给类进行初始化。(不是所有类都通过构造函数初始化,因为有些类不需要创建对象)
class StaticCode
{
static int num;
static//静态代码块,没有名字,所以无法被调用,类一加载就执行了
{
num=10;
System.out.println("hello");
}
static void show()
{
System.out.println(num);
}
}//整个类没有特有数据,不需要创建对象调用函数,就无法通过构造函数初始化,所以采用静态代码块
//全是静态成员的类不需要创建对象,为了保证不让其他成员创建对象,将构造函数私有化
//private StaticCode() {}
class StaticCodeDemo
{
pubilc static void main(String[] args)
{
new StaticCode().show();
new StaticCode().show();//两次调用输出结果为:hello 10 10,因为静态代码块只加载一次
StaticCode.show();//直接用类名调用静态函数show(),对num初始化,这里将Num初始化值放到静态代码块里
}
}
构造代码块
可以给所有对象进行初始化,每个对象都经过同样的初始化,即通用初始化;构造函数是针对对应的对象进行初始化,即针对初始化。
注意构造代码块,静态代码块和局部代码块的区别。
- 构造代码块给所有对象进行初始化,创建几个对象就调用几次。
- 静态代码块只加载一次,用于初始化类。
- 局部代码块限定函数中变量的生命周期,执行完就自动释放掉。
class StaticCode{
int age;
static//静态代码块
{
System.out.print("static ");
}
{//构造代码块
System.out.print("55 ");
}
void show()
{
{ // 局部代码块,在函数里
int age=30;
}
System.out.print("show:"+age+",");
}
}