static关键字
英文翻译为静止的、静态的,在Java语言中也取同样的意思
在Java中static关键字可以修饰成员方法和成员属性(变量);
即静态方法和静态属性
public class Chinese {
private int id;
private String name;
private static String Nationality = "China";
Chinese(){}
Chinese(int id, String name){
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public static void setNationality(String nationality) {
Nationality = nationality;
}
public static String getNationality() {
return Nationality;
}
}
public class StaticTest {
public static void main(String[] args) {
Chinese bin = new Chinese();
System.out.println(Chinese.getNationality());
}
}
/*
China
*/
上述代码定义了一个静态变量国籍,对与中国人来说国籍肯定只有一个,所以对于Chinese这个类来说,国籍是这个类中所有实例对象都有的相同的值,我们在这里用static去修饰它。
在最后的输出语句中我们可以发现我们是直接使用类名去调用这个静态变量并且成功了。
我们再把之前的测试类修改一下
public class StaticTest {
public static void main(String[] args) {
System.out.println(Chinese.getNationality());
Chinese bin = new Chinese();
System.out.println(Chinese.getNationality());
}
}
输出结果
China
China
在我们第一句中我们并没有创建一个Chinese的对象,但是通过类名我们直接调用了这个静态变量
什么原因?
原因是静态变量在类加载的时候就被赋值存在了,也就是说静态变量即不存在与堆内存空间中也不存在与栈内存空间中,而是存在于方法区内存空间中。
在上面的代码中我们也能发现,我们是使用的静态方法访问的静态变量
其实可以使用非静态的方法访问静态变量,但是静态方法只能访问静态变量
public static int getId() {
return id;
}
/*修改之前的代码,在Chinese类中的getId()方法加了static修饰符
结果是编译无法通过
Error:(26, 16) java: 无法从静态上下文中引用非静态 变量 id
*/
总结:static修饰的变量在类加载的时候加载,即静态变量早于对象存在(可以认为这是类级别的),被该类下所有对象所共有,可以直接通过"类名."的形式访问当然也可以通过实例对象进行访问;static修饰的方法即静态方法,静态方法只能访问静态变量,且在静态方法中没有也不能使用this和super关键字。
//补充静态代码块
public class Static {
static {
System.out.println(11111);
}
public static void main(String[] args) {
System.out.println(22222);
}
static {
System.out.println(33333);
}
}
//输出结果
/*
11111
33333
22222
*/
前面有提过,static修饰的变量是在类加载的时候完成赋值的,而静态代码块,也是如此,当类在方法去加载即由源码转为字节码的时候,static修饰的静态代码块在此时加载执行。
final关键字
关于final关键字,final可以修饰类、变量、方法、
被final修饰的类不能被继承,但是可以继承其他类,
被final修饰的方法不能被重写,但是子类可以调用,即该方法无法被覆盖
下面展示的代码为子类中不能重写final修饰的代码
//----------------------父类
public class Animal {
private String name;
private String type;
public Animal(){}
public Animal(String name,String type){
this.name = name;
this.type = type;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setType(String type) {
this.type = type;
}
public String getType() {
return type;
}
public final void eat(){
System.out.println("吃东西!!!");
}
}
//----------------------子类
public class Dog extends Animal{
public Dog(){}
public Dog(String name,String type){
super(name, type);
}
@Override
public void setName(String name) {
super.setName(name);
}
@Override
public String getName() {
return super.getName();
}
@Override
public void setType(String type) {
super.setType(type);
}
@Override
public String getType() {
return super.getType();
}
public void eat(){
System.out.println("吃东西");
}
}
//----------------------测试类
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
}
}
/*结果是
Error:(28, 17) java: com.demo.pojo.Dog中的eat()无法覆盖com.demo.pojo.Animal中的eat()
被覆盖的方法为final
*/
关于final修饰的变量:
1、静态常量:public static final double PI = 3.14159;,在Java中常量为static + final + 类型 + 全大写的英文单词(多个单词单词之间需要用"_"下划线隔开);(final + static 这样写好像也可以),当然只能被赋值一次,不能被修改。
2、成员常量:即被final修饰的成员变量,在定义的时候被赋值,也可以在构造方法中对其进行赋值,其实final修饰的成员变量无论是在定义的时候赋值还是在构造方法中赋值,都是在构造方法中进行赋值,定义的赋值其实是在构造方法中隐式的执行了赋值,且只能赋值一次。下面的代码展示
//赋值方式 1
public class Animal {
private final int id = 001;
}
//赋值方式 2 使用第二种方式一旦赋值,即按照这样写之后,有参的构造方法中不能出现这个成员常量,因为已经赋值一次了。
public class Animal {
final int id;
public Animal(){
this.id = 10;
}
}
final修饰的局部变量:即在方法中存在的一些变量,可以先声明再赋值,当然赋值只有一次。
权限访问修饰符
权限访问修饰符 | 所在类 | 子类 | 所在包 | 任意位置 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
默认 | √ | × | √ | × |
private | √ | × | × | × |
顾名思义。以上符号都是为了控制访问权限的,即保护用户数据和开发者书写的方法、类