1、Final(不可改变的意思)修饰时
Final类不能被继承,不能有子类防止被继承
Final方法内数据不可变,所以子类不能覆盖父类或者说防止方法的重写
Final变量是常量
-
常量的话必须要显示初始化或者说手动初始化(因为没有默认值必须有一个特定值)有直接赋值,或者构造方法赋值或者代码块里赋值。
-
常量只能赋值一次,第二次赋值会报错。
final修饰的引用类型变量只能始终引用一个变量(只能有一个内存地址),相当于一个变量新建过一个对象了,不能用一个新对象赋值给对象,但是可以修改对像里的成员变量。
引用类型变量只能始终引用一个变量的例子,用第二个报错。
修改对像里的内容的例子。
2、Static修饰符
1、静态变量相当于全局变量,所以不能在方法或代码块中定义,因为方法中的变量是局部的,而静态变量是全局的,局部变量是在栈内存(还有引用变量)的,而全局变量是在方法区(保存类数据结构,如类信息,类静态方法和变量等)
2、关于静态方法访问的问题
- 类里的静态方法可以直接调用静态方法:(private也是可以的)通过类名点去调用静态方法或者静态变量,如果用new新建对象去调用静态方法,不会报错但是会有警告(警告:The static method getprivate() from the type Test should be accessed in a static way 翻译:应以静态方式访问类型测试中的静态方法getprivate(),也就是最好用类名的方式去调用静态方法)
静态方法不能直接调用非静态方法,必须先要新建类的对象,然后用过对象点去调用静态方法。最明显的例子是main主函数也是静态方法,当要调用类中的非静态方法时,必须通过对象去调用 - 静态方法不能访问到实例变量和实例方法,也就不能在静态方法里用this。同理也就不能super,super是调用父类的实例方法或者实例变量。
package day0301;
class C {
private int a=2;
static int val=10;
static void f() {
C c=new C();
c.x();
System.out.println("静态方法的输出");
int sum=val/a;//会报错,静态方法不能访问实例变量
}
void x() {
System.out.println("非静态方法的输出");
}
public static void main(String[] a) {
C.f();
}
}
3、静态代码块:会在首次载入该类且首次使用该类前执行static代码块
例子1
class W {
static double a;
static double b;
static {
System.out.println("静态代码块加载");
System.out.println("-------------------");
a = Math.sqrt(2.0);
b = Math.sqrt(3.0);
}
W() {
System.out.println("输出实例变量");
}
}
public class C {
public static void main(String[] args) {
W c = new W();
System.out.println(W.a + "--" + W.b);
W e = new W();
System.out.println(W.a + "--" + W.b);
}
}
控制台输出:
静态代码块加载......
输出实例变量
1.4142135623730951--1.7320508075688772
输出实例变量
1.4142135623730951--1.7320508075688772
例子2 没有继承,且主函数不在Dog类里
类的初始化是指类加载过程中的初始化阶段对类变量按照程序猿的意图进行赋值的过程;而类的实例化是指在类完全加载到内存中后创建对象的过程。类初始化后可以没有实例对象
package day0301;
class Dog {
private int number;
static {
System.out.println("静态代码块加载......");
System.out.println("-------------------");
}
}
//没有继承,且主函数不在Dog类里
public class C {
public static void main(String[] args) {
//类的初始化是指类加载过程中的初始化阶段对类变量按照程序猿的意图进行赋值的过程;
//而类的实例化是指在类完全加载到内存中后创建对象的过程。类初始化后可以没有实例对象
Dog dog1 = null;//初始化了Dog类但是还是没有对象
Dog dog2 = dog1;//初始化了Dog类但是还是没有对象
System.out.println("hello");
}
}
控制台输出:
Hello
例子3 有继承
class Dog {
private int number;
static {
System.out.println("静态代码块加载......");
System.out.println("-------------------");
}
}
//有继承
public class C extends Dog{
public static void main(String[] args) {
Dog dog1 = null;
Dog dog2 = dog1;
System.out.println("hello");
}
}
控制台输出:
静态代码块加载......
-------------------
Hello
例子4 在同一个类
class Dog {
private int number;
}
public class C {
static {
System.out.println("静态代码块加载......");
System.out.println("-------------------");
}
public static void main(String[] args) {
C dog1 = null;
C dog2 = dog1;
System.out.println("hello");
}
}
控制台输出:
静态代码块加载......
-------------------
Hello
3、abstract修饰符
abstract类:
抽象类除了不能创建实例,和一个普通类没有区别,抽象类也有属性,构造方法,方法包括静态和非静态方法,静态代码块等.
- 可以有构造方法,但是抽象类不能创建实例,所以只能通过继承子类去实例化
- 不能加private、static、final
- 可以没有抽象方法(比如有静态方法或者非静态),但一旦有一个方法是abstract那么类就要定义成abstract
Abstract方法:
- 没有方法体{里面为空}
- 通过子类去重写全部的abstract的方法,如果没有全部重写子类也要定义为Abstract
Abstract方法和static不能连用:
static它是类自己的东西且是公共的东西。如果类把类比作一个合租房子,那么static就像是公共空间的厨房,所以只能使用,不能带走,所以是不能继承的。
abstract本身没有实现,所以目的是给子类继承的,相当于看房后给你的一个房间,会提供一些基本东西,但是很多都是要你自己去实现自己去买的,一旦实现了就都是你的了,也能看出两者的内存地址会不一样。
Abstract方法和final不能连用
Final不能被继承也不能修改方法和abstract的目的完全相反。