一、构造方法(封装)
1构造方法的定义和使用
Person p = new Person();
1)构造方法:构造函数,构造器,Constructor
2)构造方法的作用:
为对象中的成员变量进行赋值,当创建对象同时,构造方法主动调用
等对象创建完毕,对象中的成员变量就有值了
3)构造方法定义语法结构:
修饰符 构造方法名(参数列表){
方法体;// 通常使用构造进行成员变量的赋值
}
4)解释:
1) 修饰符 : 通常使用public 公共的修饰
2) 构造方法没有返回值类型, 连void都不写
3) 构造方法名必须与类型保持一致,连大小写都必须一样
4) 因为构造没有返回值类型,因此构造中可以没有return, 如果一定要写, return;
5)构造方法的运行机制:
每次创建对象, 构造方法会被JVM虚拟机主动调用一次, 构造方法不能被对象名.手动调用
举例
public classPerson {//定义出私有成员变量
privateString name;private intage;//定义出一个构造,为了给成员变量进行赋值
publicPerson() {
name= "张三";
age= 20;
System.out.println("我是空参数构造,我执行了");
}public voidsetName(String name) {this.name =name;
}publicString getName() {returnname;
}public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}
}
public classTestPerson {public static voidmain(String[] args) {//1. 空参数构造的调用
Person p = newPerson();
System.out.println(p.getName());
System.out.println(p.getAge());//构造方法无法被手动调用//p.Person();
Person p1= newPerson();
Person p2= newPerson();
}
}
2 构造方法使用的注意事项
构造方法的参数列表:
1) 构造方法可以没有参数, 创建对象同时,()中就是空的, 只能在构造方法中给成员变量赋值默认值
2) 构造方法可以有参数, 创建对象同时, ()中需要提供构造实际参数, 可以通过参数列表给成员变量进行赋值
2.如果类中,没有定义任何的构造方法,那么系统自动为类型创建出一个空参数的构造方法,空参数构造使用 public修饰, 构造方法中,没有任何逻辑
3.如果类中, 已经手动定义了构造方法(不论构造有无参数列表), 那么系统不会自动添加任何构造
4.构造方法可以重载:
定义在同一个类中, 方法名相同, 方法的参数列表不同, 与方法的返回值类型无关,多个方法之间,称为方法重载(Overload)
1) 构造方法名全部与类名一致, 方法名相同
2) 方法的参数列表不同 : 自己把握
3) 与方法的返回值类型无关 : 构造方法没有返回值类型
代码
public classPerson {//定义出私有成员变量
privateString name;private intage;//定义出一个构造,为了给成员变量进行赋值
publicPerson() {
name= "张三";
age= 20;
System.out.println("我是空参数构造,我执行了");
}//定义出一个构造,通过构造方法参数列表给成员变量进行赋值
public Person(String name, intage) {this.name =name;this.age =age;
System.out.println("我是有参数构造,执行了~~~~~~~~~~");
}public voidsetName(String name) {this.name =name;
}publicString getName() {returnname;
}public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}
public classTestPerson {public static voidmain(String[] args) {//1. 空参数构造的调用//The constructor Person() is undefined
Person p = newPerson();
System.out.println(p.getName());
System.out.println(p.getAge());//构造方法无法被手动调用//p.Person();
Person p1= newPerson();
Person p2= newPerson();//2. 有参数构造调用,需要创建对象同时,传递实际参数
Person p3 = new Person("小花",19);
System.out.println(p3.getName());
System.out.println(p3.getAge());
Person p4= new Person("QQ",17);
System.out.println(p4.getName());
System.out.println(p4.getAge());//3. 如果类型中,没有定义任何的构造方法,那么系统自动为类型创建出一个空参数的构造方法//空参数构造使用 public修饰, 构造方法中,没有任何逻辑
Person p5 = newPerson();
}
3.this关键字在构造方法中的使用
构造方法之间,可以互相调用
使用this(被调用的构造实际参数) , 可以调用另外一个构造方法、
2.this() 本类构造方法之间的调用 : 要求this()必须放在构造方法有效行第一行
3.总结this关键字的使用
1) this关键字用于区分成员变量和局部变量重名问题, 带有this关键字的变量表示成员变量的使用
2) this() : 表示本类构造之间的调用, ()需要传递实际参数, this()必须在构造方法有效行第一行
代码
public classThisAndCon {privateString name;private intage;//1. 定义出一个空参数构造
publicThisAndCon() {
System.out.println("空参数构造");
}//2. 定义出一个有参数构造
public ThisAndCon(String name, intage) {//this()表示调用空参数构造//this();//this(name) : 表示有参数构造调用
this("小美");//Constructor call must be the first statement in a constructor//this.name = name;
this.age =age;
System.out.println("有参构造执行了");
}//3. 定义出一个有参数构造
publicThisAndCon(String name) {this.name =name;
System.out.println("给name赋值");
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}
public classTestThis关键字在构造中的使用 {public static voidmain(String[] args) {
ThisAndCon tac= new ThisAndCon("小花",25);
System.out.println(tac.getName());
System.out.println(tac.getAge());
}
4.构造方法和set赋值比较
构造方法无法取代set方法给成员变量赋值过程
1.构造只能在创建对象同时,给对象中的成员变量进行一次赋值,无法通过构造改值
2.set赋值 : 发生在创建对象之后, 使用对象名.调用set方法给对象中的成员变量进行赋值, 方法可以多次调用,每次调用都可以修改对象中成员变量的值
5.创建对象给成员变量赋值的过程
创建一个对象时, 给这个对象的成员变量赋值,有3种方式:
1) JVM虚拟机默认赋值
2) 成员变量的显示赋值
3) 构造方法赋值
2.三种方式赋值过程:
1) 首先将对象的成员变量加载进堆内存中, JVM虚拟机进行默认的赋初值动作
2) 如果成员变量有显示赋值(定义成员变量时, 直接赋值). 显示赋值覆盖掉JVM虚拟机赋值
3) 如果有构造方法赋值, 那么构造赋值覆盖掉显示赋值, 最终以构造赋值为标准
代码
public class对象创建成员赋值过程 {//姓名
String name;//年龄 age的显示赋值,覆盖掉JVM默认赋值0
int age = 20;//性别 sex的显示赋值,覆盖掉JVM默认赋值null
String sex = "男";//定义出一个构造
public对象创建成员赋值过程() {//sex的构造赋值覆盖掉了 显示赋值
sex = "nv";
}
}
public classTest创建对象成员赋值过程 {public static voidmain(String[] args) {
对象创建成员赋值过程 demo= new对象创建成员赋值过程();
System.out.println(demo.age);//20
System.out.println(demo.name);//null
System.out.println(demo.sex);//nv
}
二、静态static
1 静态概念的引入
没有静态场景:
类型Student, 所有学生对象具有相同的属性值,就是schoolName = "第一中学", 发现问题 : 每一个对象都需要存储并且维护相同的属性值
1) 相同的属性,在每一个对象中都存储,浪费内存
2) 维护难度大,如果修改校名, 所有对象都需要修改校名
有静态场景 :
将所有对象相同属性,在类型中使用static静态关键字进行修饰, 使用静态修饰的成员存储在方法区中,可以被所有的对象所共有使用, 是静态所表现出的共享性
2.静态的特点
1.static : 关键字, 表示静态,静止的
2.静态属于类, 不属于任何对象;
3.静态优先于对象存在, 但是可以被对象共享使用
4.静态成员使用方式:
1) 类名.直接调用; (最推荐)
2) 使用 对象名.调用; (不推荐)
代码
public classStaticStudentTest {public static voidmain(String[] args) {
Student s= newStudent();//The static field Student.schoolName should be accessed in a static way//System.out.println(s.schoolName);//第一中学
System.out.println(Student.schoolName);//s.schoolName = "一中";
Student.schoolName = "一中";
Student s1= newStudent();
System.out.println(s1.schoolName);//一中
}
3.静态使用的注意事项
静态方法中不能直接使用非静态(成员变量,非静态方法)
静态方法中,不能直接使用非静态成员变量
静态成员跟着类先进入内存, 非静态成员变量,跟着对象的创建后进入到堆内存中,先进入内存中的方法,无法直接使用后进入到内存中的成员
3.静态方法中, 不能直接调用非静态方法使用
静态成员跟着类先进入内存, 非静态方法需要在创建对象之后才能使用,先进入内存中的方法,无法直接使用后进入到内存中的非静态方法
4.静态方法中,不能使用this关键字
this表示本类对象的引用, 需要先创建出对象, this才能引用, 而静态优先于对象存在, 因此不能直接使用this关键字
代码
public classDemo01_静态中不能使用非静态 {//1. 成员变量,定义一个非静态成员
int i = 10;public static voidmain(String[] args) {//2. 静态方法中不能直接使用非静态成员变量//System.out.println(i);//3. 可以通过创建对象,调用非静态成员
Demo01_静态中不能使用非静态 demo = newDemo01_静态中不能使用非静态();
System.out.println(demo.i);//10//4. 静态方法中不能直接调用非静态方法//eat();
demo.eat();//5. 因为静态优先于对象存在, 所以静态方法中, 不能直接使用this关键字//System.out.println(this.i);//Cannot use this in a static context
}public voideat() {
System.out.println("我在吃饭");
}
4.静态成员变量和非静态成员变量的区别
1.所属不同:
a : 静态成员变量 : 属于类
b : 非静态成员变量 : 属于对象
2.在内存中存储区域不同:
a : 静态成员变量 : 跟着类存储在方法区中
b : 非静态成员变量 : 跟着对象存储在堆内存中
3.生命周期不同:
a : 静态成员变量 : 跟着类进入方法区,存在了;当类从方法区消失(将类中的所有内容全部运行完毕), 静态成员消亡
b : 非静态成员变量 : 创建对象时, 存在了; 当对象再也没有任何使用的地方, 非静态成员变量跟着对象消亡
4.调用方法不同:
a : 静态成员变量: 1) 类名.直接调用 2) 对象名.调用
b : 非静态成员变量 : 对象名.调用
三、代码块
代码块 : 使用一对大括号包裹起来的一段代码, 将代码块放置到不同的位置, 具有不同的功能, 有不同运行机制
代码块的分类:
1) 局部代码块
2) 构造代码块
3) 静态代码块
4) 同步代码块(非常重要,多线程)
1.局部代码块
格式 : 代码使用一对大括号包裹起来
位置 : 方法中
作用 : 限定 定义在局部代码块中的变量作用范围, 如果变量无法再使用,这个变量所占有的内存空间就会被释放回收, 减少变量在内存中占有的时间, 节省内存
注意:
1) 局部代码块, 只限定 定义在局部代码块中的变量
2) 定义在局部代码块之外的变量, 局部代码块对其没有影响效果
举例 : 定义在局部代码块之外的变量i, 如果在局部代码块中修改值, 出了局部代码块之外,修改仍然生效
代码
public classDemo01_局部代码块 {public static voidmain(String[] args) {int i = 10;//局部代码块: 限定定义在局部代码块中的变量使用范围
{
i= 99;//赋值,不受代码块影响
int y = 20;
System.out.println(i+ y);//119
}//y cannot be resolved to a variable//System.out.println(y); 超出了y的使用范围
System.out.println(i);//99
}
2.构造代码块
格式 : 代码使用一对大括号包裹起来
位置 : 类中方法外
作用 :
1) 可以通过构造代码块给成员变量进行赋值(默认赋值)
2) 如果多个构造方法都具有相同的处理逻辑,可以将相同的逻辑提升到构造代码块中实现和运行
4.运行机制:
每次创建对象时, JVM虚拟机主动调用构造代码块一次, 在构造方法执行之前调用
代码
public classDemo02_构造代码块 {inti;//构造代码块 : 给成员赋值
{
i= 10;
System.out.println("构造代码块运行了");
System.out.println("构造执行~~~~~~~");
}publicDemo02_构造代码块() {//System.out.println("构造执行~~~~~~~");
}public Demo02_构造代码块(inti) {this.i =i;//System.out.println("构造执行~~~~~~~");
}public static voidmain(String[] args) {
Demo02_构造代码块 demo= newDemo02_构造代码块();
System.out.println(demo.i);
Demo02_构造代码块 demo1= new Demo02_构造代码块(99);
}
3. 静态代码块(掌握)
格式 :
static {
代码;
}
2.位置 : 类中方法外
3.作用 :
1) 可以给静态成员变量进行赋值(默认值)
2) 如果有代码功能, 在类进入内存时,就需要马上执行,并且只执行一次,那么代码可以设计在静态代码块中
运行机制:
当类加载进入到方法区时(使用这个类时), JVM虚拟机主动调用一次静态代码块,与创建多少次对象,后续使用无关
代码块的运行顺序:
静态代码块--->构造代码块--->构造方法
public classDemo03_静态代码块 {static intj;
{
System.out.println("构造代码块");
}//静态代码块
static{//1. 给静态成员变量赋值
j = 99;
System.out.println("静态代码块运行了");
}publicDemo03_静态代码块() {
System.out.println("构造方法~~~~~~");
}public static voidmain(String[] args) {/*System.out.println(Demo03_静态代码块.j);// 99
System.out.println(Demo03_静态代码块.j);// 99*/Demo03_静态代码块 demo1= newDemo03_静态代码块();
Demo03_静态代码块 demo2= newDemo03_静态代码块();
}