一、局部变量、成员变量和类变量
1.1 区分表
我先将局部变量、成员变量和类变量的区分表放在前面,以后的内容也会这样,先把区分表放在内容之前。后面会详细地对概念进行解释,帮助同学们更深入地理解概念。如果是仅仅想看他们的区别的话,可以只看第一部分。
局部变量 | 成员变量 | 类变量 | |
声明位置 | 方法或程序块 | 类中方法外 | 类中方法外 |
生命周期 | 方法或程序块 | 随对象的创建和销毁 | 类第一次调用生成,程序结束销毁 |
默认值 | 无 | 0、null、false、0.0 | 0、null、false、0.0 |
修饰符 | 不可修饰 | 访问修饰符,一般为private | static、final和访问修饰符,一般为private |
内存分配 | 栈内存 | 堆内存 | 静态存储区 |
其他类中的使用方式 | 不可使用 | 对象名.变量名 | 类名.变量名 |
1.2 概念区分
1、局部变量:代码和程序块中的变量,只在代码和程序块中使用。局部变量存储在栈内存中,随代码和程序块的结束而销毁。局部变量没有修饰符。由于其内存会随着代码和程序块的结束而被销毁,所以在其他的方法和类中无法直接调用局部变量,除非是该代码和程序块的子程序块。
2、成员变量:在类中定义的变量和方法叫做成员变量和成员方法。成员变量与成员方法在类中同级,通常成员变量定义在成员方法之前,成员变量可以在类的成员方法中被使用。可以通过访问修饰符private、protected和public来进行修饰,如果不加访问修饰符,则默认其为default修饰,不同修饰符对变量产生的影响会在下面的访问修饰符内进行区分。
由于Java的封装性,我们一般使用private修饰符修饰成员变量。在成员方法中直接使用成员变量的变量名或者通过“this.变量名”进行调用。在Java中我们在构建一个类的对象的时候,会通过类构造方法对类的成员变量进行赋值。如果没有定义构造方法,Java会自动生成一个不带参数的构造方法,为根据对象的成员变量的类型为其赋初始值,一般为0、null、false、0.0。
在理解上,我认为成员变量属于对象,而类变量属于类。因为成员变量的构建和销毁是跟随对象的,而类变量则是存储在静态存储区,被所有类的对象所共享。
3、类变量:类变量和成员变量定义在一起,在某种角度来看,它算作一种特殊的成员变量,只不过它除了可以使用“对象.变量名”来进行调用,还可以通过类来进行调用,如果它是public的。这里注意,所有成员方法可以正常调用类变量,静态方法只能调用类变量。
类变量同样可以使用访问修饰符来进行修饰,但是它需要使用static来进行修饰。存储的位置也变成了静态存储区。除此之外,它还可以使用final来进行修饰,被final修饰后,它就相当于一个类的常量,无法被修改,且只能通过类进行调用。
1.3 实例验证
我们定义一个Person类,内容如下。为了示范他们的功能,我们这里尽量简化代码。我们可以看到类变量可以在成员方法中使用。但是被final控制的那个无法再进行赋值。
public class Person {
//静态变量
private static Integer personCount;
public static final String disc = "善良";
//成员变量
private Integer personNum = 0;
public Person(Integer personNum) {
//局部变量
int tmpInt = 1;
this.personNum = personNum;
personCount++;
}
public void printPerson(){
System.out.println(personNum+personCount+disc);
/*错误,不可赋值
disc = "中二";*/
}
}
我们再定义一个类,使用Person。可以看出一个公共的类变量可以通过类名直接进行调用。
public class TestSeason {
public static void main(String[] args) {
Person person = new Person(1);
System.out.println(Person.disc);
System.out.println(person.disc);
person.printPerson();
}
}
二、访问控制修饰符
2.1 区分表
修饰符 | 当前类 | 同包类 | 不同包子类 | 不同包除子类 | 子类重写方法的控制符 |
public | Y | Y | Y | Y | public |
protected | Y | Y | 可继承,不可调用 | N | protected、public |
default | Y | Y | N | N | default、protected、private |
private | Y | N | N | N | 不可重写 |
如果你觉得这样还是不好理解,可以这样想:
1、访问控制的宽松度:public>protected>default>private,在继承的时候可以越来越宽松
2、default只能在同包的类中使用,当然,不是这个方法的子类无论在那里都无法重写父类方法。
3、protected因为宽松度比default大,所以default能使用的地方,它一定可以。而它控制的方法一定能够被该类的子类重写。
2.2 概念区分
访问控制符是用来控制成员变量、成员函数和内置类的访问权限,一般我们会将成员变量的访问权限设置为私有,方法设置为共有。我们可以显式设置变量或方法为public、protected和private,如果不设置则为default。这里就不对概念做太多解释了,权限控制,在上表中已经说的很清楚了。
三、抽象类与接口之间的区别
抽象类 | 接口 | |
是否可以被多继承 | N | Y |
方法抽象 | 可以,但不必须 | 必须全部 |
方法静态 | 可以,但不必须 | N |
方法公有 | 可以,但不必须 | 必须是 |
方法是否有具体实现 | Y | N |
变量修饰符 | 没有要求 | public static final |
是否有构造方法 | 可以有 | N |
声明关键字 | abstract | interface |
是否可以实例化对象 | Y | N |
四、static和final之间的区别
final | static | |
修饰 | 属性、方法、类(包括内部类)、局部变量 | 属性、方法、代码段、内部类 |
初始化 | 编译或运行 | 编译 |
修饰属性 | 创建后不可修改,相当于常量,可以在构造函数中初始化 | 所有该类对象所共有 |
修饰方法 | 不能被重写 | 只能使用类进行直接调用 |
暂时只有这四个概念是我觉得比较模糊的,如果大家有哪里看不懂或者有其他分不清的概念,可以给我留言,我会继续补充