Java基础(七)——面向对象基础(二)
一、构造方法
1、无参构造方法
调用属性是 对象.属性
来调用,调用方法是 对象.方法()
来调用。可以看到区分属性跟方法就在于后面有没有小括号,有就是方法。
实例化对象的时候,是这样:
Teacher tea1 = new Teacher() // 实例化一个对象
可以看到,等号右边,这个类有个小括号,这个有在调用一个方法,就是构造方法。
a、构造方法的调用
每次实例化一个对象的时候,就会调用构造方法:
public class Teacher{
int id;
String name;
public Teacher(){
// 无参构造方法
System.out.println("这里是无参构造方法");
}
}
可以看到,上面的构造方法,名字跟类是一样的。
所以,使用构造方法,就是:public 类名
b、无参构造方法
这个构造方法,没有接收参数,所以称为无参构造方法。
构造方法如果有 return 语句,会报错,所以构造方法不能有返回值。
构造方法无论我们在不在类里面定义,都能实例化对象。说明构造方法默认存在。
2、有参构造方法
当无参构造方法接收参数进行数据处理,就是有参构造方法。
public Teacher(int i,String str){
//有参构造方法
System.out.println("这里是有参构造方法");
}
a、有参构造方法创建对象
因为每次实例化对象都会执行构造方法,所以可以通过有参构造方法,在实例化对象的时候就赋值,就可以无需通过 set 方法来赋值。
public Teacher(int i,String str){
// 有参构造方法
id = i;
name = str;
System.out.println("这里是有参构造方法");
}
b、通过有参构造方法实例化对象
在实例化的对象的时候就进行赋值:
Teacher tea1 = new Teacher(1,"张三); // 实例化对象的同时进行赋值
这样创建出来的 tea1 对象就有了id和姓名,就不需要set 方法来进行初始赋值。
3、构造方法总结
- 构造方法不能有返回值,方法名和类名一致。
- 无参构造方法默认存在。
- 无参构造方法作用:初始化属性和创建对象。
- 有参构造方法作用:创建对象的同时给一个或者多个属性赋值。-------相当于无参+多个set()
- 当有参构造方法创建的时候,默认的无参构造方法会消失。需要使用的时候必须手动创建。
二、全局变量与局部变量
1、全局变量与局部变量
因为贯彻见词知意,所以构造方法形参这块,不应该用像 i ,str 这类单词,应该:
public class Teacher{
int id;
String name;
public Teacher(int id,String name ){
// 有参构造方法
id = id;
name = name ;
System.out.println("这里是有参构造方法");
}
}
如果按照以上代码运行,实例化对象,对象的 id 只能是0,name 肯定是 null。这里就要说到局部变量与全局变量的概念了。
如果在类里面,方法外面定义的变量,则是全局变量,如果是方法里面,则是局部变量。
那么全局变量与局部变量,都重名时,使用哪个变量呢?
答案是使用作用域范围小的那个变量。
所以这里使用的是方法内部的局部变量,因为只初始化了,没有赋值,所以使用的是初始化的值。
2、this
所以这里可以通过 this 这个关键字,指定这个变量是当前对象的变量,就不会产生这种作用域范围错误的问题:
public class Teacher{
int id;
String name;
public Teacher(int id,String name){
// 有参构造方法
this.id = id;
this.name = name ;
System.out.println("这里是有参构造方法");
}
}
这里通过this指定的id,就是类内部,那个全局变量的id。
3、局部变量不能做的事
- 局部变量不能存在访问修饰符,比如:public,private.
- 局部变量不存在初始值,比如:只初始化不赋值
int id
4、this调用方法
this.方法()
意思是调用当前对象的方法:
public class Teacher{
int id;
String name;
public Teacher(int id,String name){
// 有参构造方法
this.id = id;
this.name = name ;
this.method1(); // 调用下面的方法1
System.out.println("这里是有参构造方法");
}
public void method1(){
System.out.println("这里是方法1");
}
}
上面的代码中,this.method1()
会调用到下面的 method1(),
5、this调用无参构造方法
既然this代表当前对象,因此,this(),代表的是当前类对象的无参构造方法,必须注意的是:通过this调用构造方法必须在构造方法中的第一句。
6、总结
- 全局变量:定义在类中,作用域在整个类,拥有初始值和访问修饰符。
- 局部变量:定义在方法中,作用域只在方法中,没有初始值和不能存在访问修饰符。
- 当局部变量和全局变量同名的时候, 使用的时候会优先使用作用域更小的变量。
- this:代表当前对象
- this.属性——调用当前类对象的属性
- this.方法() – 调用当前类对象的方法
- this() – 调用当前类对象的无参构造方法,且通过 this 调用构造方法必须在构造方法中的第一句。
三、static关键字
1、static修饰变量(静态属性)
实例属性是每个对象各自持有的独立空间(多份),对象单方面修改,不会影响其他对象。
比如:对象1的年龄与对象2的年龄,对象1年龄改变,对象2的年龄不会改变。
被 static 修饰的属性,称为静态属性。static int age;
但是,静态属性是整个类共同持有的共享空间(一份),任何对象修改,都会影响其他对象。
运行后的结果是:
可以看到,本来第一个老师的money应该是1000,但这里却变成了2000。因为money是静态属性,共用一块内存空间,后面的tea2赋值了money是2000,所以后面的对象输出money都是2000。
2、static修饰方法(静态方法)
static修饰的方法称为静态方法。
a、类直接调用静态方法
静态方法可以被类直接调用,不需要经过实例化对象。
定义类:
public class Animal {
String name;
int leg;
static String sex;
public static void method1(){
// 静态方法
sex = "母";
System.out.println("123"+","+sex);
}
}
类直接调用:
Animal.method1(); // 类能直接调用
b、静态方法只能调用静态属性
public class Teacher {
static int id; //静态属性
int num;
public static void method01(){
//静态方法
System.out.println("静态方法");
//静态方法不允许调用非静态属性
//System.out.println(num);
System.out.println(id);
//静态方法不允许调用普通方法
//method02();
}
//普通方法
public void method02(){
}
}
静态方法只能调用静态属性,通过测试先后顺序就可以得知,加了 static 关键字的属性或者方法,也就是静态属性/方法,比普通方法和属性更早创建,在创建静态属性/方法后,普通属性/方法还没有初始化,所以自然也无法调用普通属性/方法。
3、static(静态)无法修饰构造方法
static 修饰的属性/方法,可以被类直接调用,有点共享的思想,也先于其他属性/方法执行。
static 无法修饰构造方法,因为:构造方法是对象初始化时候执行的方法,不初始化,则不执行后面的方法,所以构造方法是源头。因为是初始化才能使用,所以不存在共享的概念,初始化之后,后面才有机会调用,所以也不需要提前执行。所以也就没有添加 static 的必要。所以 static 无法修饰的属性/方法。
4、构造代码块
public class Teacher {
{
// 构造代码块从这里开始
System.out.println("这里是代码块"); // 这里是构造代码块
} // 构造代码块从这里结束
public Teacher(){
System.out.println("这里是无参构造方法");
}
}
通过测试可知,构造代码块执行顺序优于构造方法。
同理,静态构造代码块,执行顺序优于构造代码块。
5、static 修饰的静态构造代码块
静态构造代码块有且仅有一次执行
测试:
public class Test4 {
public static void main(String[] args) {
// 测试2:静态构造代码块有且仅有一次执行
Teacher tea1 = new Teacher();
Teacher tea2 = new Teacher();
}
}
public class Teacher {
public Teacher(){
System.out.println("这里是无参构造方法");
}
{
System.out.println("这里是构造代码块");
}
static {
System.out.println("这里是静态构造代码块1");
}
}
结果是:
可以看到,静态构造代码块只执行了一次,所以,静态构造代码块有且仅有一次执行。
6、静态构造代码块与静态属性
静态构造代码块与静态属性的实行顺序是:按代码从上到下执行,谁先在前面谁先执行。
7、总结
static:静态的,被static修饰的代码会随着字节码文件(也就是.class文件)优先于类加载进内存。
static 修饰的属性为静态属性,内存中所有对象共享一份数据,通过类名直接调用。
static 修饰的方法为静态方法,直接通过类名调用,一般工具类中存在静态方法,静态方法只能调用静态属性。
static 修饰的构造代码块为静态构造代码块。在类被使用的时候,有且仅有一次执行,优先于构造代码块和构造方法。
静态属性/静态构造代码块 > 构造代码块 > 构造方法
直接通过类调用时,只会触发静态构造代码块和静态属性。 其他的均如:构造代码块和构造方法都不会触发。
只有实例化对象时,才会触发构造代码块和构造方法。