day01——面向对象高级
一、静态
接下来,我们学习一下面向对象编程中很常见的一个关键字static.
static读作静态,可以用来修饰成员变量,也能修饰成员方法。我们先来学习static修饰成员变量。
1.1 static修饰成员变量
Java中的成员变量按照有无static修饰分为两种:类变量、实例变量。它们的区别如下图所示:
由于静态变量是属于类的,只需要通过类名就可以调用:类名.静态变量
实例变量是属于对象的,需要通过对象才能调用:对象.实例变量
- 下面是代码演示(注意静态变量,和实例变量是如何调用的)
为了让大家对于这两种成员变量的执行过程理解更清楚一点,在这里给大家在啰嗦几句,我们来看一下上面代码的内存原理。
- 最后总结一下
- 1.类变量:属于类,在内存中只有一份,用类名调用
- 2.实例变量:属于对象,每一个对象都有一份,用对象调用
1.3 static修饰成员方法
各位同学,学习完static修饰成员变量之后,接下来我们学习static修饰成员方法。成员方法根据有无static也分为两类:类方法、实例方法
有static修饰的方法,是属于类的,称为类方法;调用时直接用类名调用即可。
无static修饰的方法,是属于对象的,称为实例方法;调用时,需要使用对象调用,用类名调用会报错,不知道调用哪个类中的方法。
我们看一个案例,演示类方法、实例方法的基本使用
- 先定义一个Student类,在类中定义一个类方法、定义一个实例方法
public class Student{
double score;
//类方法:
public static void printHelloWorld{
System.out.println("Hello World!");
System.out.println("Hello World!");
}
//实例方法(对象的方法)
public void printPass(){
//打印成绩是否合格
System.out.println(score>=60?"成绩合格":"成绩不合格");
}
}
- 在定义一个测试类,注意类方法、对象方法调用的区别
public class Test2{
public static void main(String[] args){
//1.调用Student类中的类方法
Student.printHelloWorld();
//2.调用Student类中的实例方法
Student s = new Student();
s.printPass();
//使用对象也能调用类方法【不推荐,IDEA连提示都不给你,你就别这么用了】
s.printHelloWorld();
}
}
搞清楚类方法和实例方法如何调用之后,接下来再啰嗦几句,和同学们聊一聊static修饰成员方法的内存原理。
1.类方法:static修饰的方法,可以被类名调用,是因为它是随着类的加载而加载的;
所以类名直接就可以找到static修饰的方法
2.实例方法:非static修饰的方法,需要创建对象后才能调用,是因为实例方法中可能会访问实 例变量,而实例变量需要创建对象后才存在。
所以实例方法,必须创建对象后才能调用。
关于static修饰成员变量、和静态修饰成员方法这两种用法,到这里就学习完了。
补充知识:
搞懂main方法:
1.4 工具类
学习完static修饰方法之后,我们讲一个有关类方法的应用知识,叫做工具类。
如果一个类中的方法全都是静态的,那么这个类中的方法就全都可以被类名直接调用,由于调用起来非常方便,就像一个工具一下,所以把这样的类就叫做工具类。
在补充一点,工具类里的方法全都是静态的,推荐用类名调用为了防止使用者用对象调用。我们可以把工具类的构造方法私有化。
为什么工具类要用类方法,而不是实例方法?
- 实例方法需要创建对象来调用,会浪费内存
public class MyUtils{
//私有化构造方法:这样别人就不能使用构造方法new对象了
private MyUtils(){
}
//类方法
public static String createCode(int n){
...
}
}
1.5 static的注意事项
各位同学,到现在在我们已经学会了static修饰的变量、方法如何调用了。但是有一些注意事项还是需要给大家说明一下,目的是让大家知道,使用static写代码时,如果出错了,要知道为什么错、如何改正。
public class Student {
static String schoolName; // 类变量
double score; // 实例变量
// 1、类方法中可以直接访问类的成员,不可以直接访问实例成员。
public static void printHelloWorld(){
// 注意:同一个类中,访问类成员,可以省略类名不写。
schoolName = "黑马";
printHelloWorld2();
System.out.println(score); // 报错的
printPass(); // 报错的
ystem.out.println(this); // 报错的
}
// 类方法
public static void printHelloWorld2(){
}
// 实例方法
public void printPass2(){
}
// 实例方法
// 2、实例方法中既可以直接访问类成员,也可以直接访问实例成员。
// 3、实例方法中可以出现this关键字,类方法中不可以出现this关键字的
public void printPass(){
schoolName = "黑马2"; //对的
printHelloWorld2(); //对的
System.out.println(score); //对的
printPass2(); //对的
System.out.println(this); //对的
}
}
1.6 static应用(代码块)
各位同学,接下来我们再补充讲解一个知识点,叫代码块;代码块根据有无static修饰分为两种:静态代码块、实例代码块
我们先学习静态代码块:
public class Student {
static int number = 80;
static String schoolName = "黑马";
// 静态代码块
static {
System.out.println("静态代码块执行了~~");
schoolName = "黑马";
}
}
静态代码块不需要创建对象就能够执行
public class Test {
public static void main(String[] args) {
// 目标:认识两种代码块,了解他们的特点和基本作用。
System.out.println(Student.number);
System.out.println(Student.number);
System.out.println(Student.number);
System.out.println(Student.schoolName); // 黑马
}
}
执行上面代码时,发现没有创建对象,静态代码块就已经执行了。
关于静态代码块重点注意:静态代码块,随着类的加载而执行,而且只执行一次。
再来学习一下实例代码块
实例代码块的作用和构造器的作用是一样的,用来给对象初始化值;而且每次创建对象之前都会先执行实例代码块。
public class Student{
//实例变量
int age;
//实例代码块:实例代码块会执行在每一个构造方法之前
{
System.out.println("实例代码块执行了~~");
age = 18;
System.out.println("有人创建了对象:" + this);
}
public Student(){
System.out.println("无参数构造器执行了~~");
}
public Student(String name){
System.out.println("有参数构造器执行了~~");
}
}
接下来在测试类中进行测试,观察创建对象时,实例代码块是否先执行了。
public class Test {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student("张三");
System.out.println(s1.age);
System.out.println(s2.age);
}
}
对于实例代码块重点注意:实例代码块每次创建对象之前都会执行一次