1.1 修饰类abstract:抽象的
例如生活中有很多动物,狗、猫、猪等等,但是这些都统称为动物,动物并不是一个实实在在的实例,所以这里的动物这个词是我们抽象出来的一个名字,而狗、猫等这些动物属于这个拥有动物特征所建立出的一个具体实例。
有的类是抽象出来的概念,只能作为父类存在,而不应该直接创建对象,此时我们可以在类上加入abstract关键词,设置为抽象类,不能直接创建对象,只能作为父类,让其子类继承。
//abstract修饰的类无法创建对象
public abstract class class_Abstract {
}
1.2 修饰方法
abstract修饰的方法为抽象方法,抽象方法没有方法体,由子类去定义抽象方法的内容,一般我们将子类重写父类的一个方法定义为抽象方法。
例如:之前我们创建的Animal、Dog、Cat类,我们可以将Animal定义为抽象类,将他的eat方法可以定义为抽象方法,因为子类都会去重写这个类。
public abstract class class_Abstract {
abstract void method_Abstract();
}
注意:
-
一个抽象类可以没有抽象方法;
-
一个抽象方法必须在抽象类中;
-
抽象方法不能用private,否则无意义,因为抽象方法就是为了继承给子类重写;
-
当子类继承一个有抽象方法的抽象类时,会报错,解决方案如下:
-
将子类也设置为抽象类
-
重写父类中所有的抽象方法
-
2.1 修饰类final:最终的、最后的、终结的
当修饰类时表示该类不可被继承,因此注意final和abstract无法一起使用,abstract就是为了给子类继承编写,但是final无法继承。
public final class class_Abstract {
}
2.2 修饰方法
当修饰方法时表示该方法不可被重写。
public final void method_Abstract(){
}
2.3 修饰变量
表示该变量一旦赋值就不可改变,称为常量。
2.3.1 修饰属性
当修饰属性后,该属性必须要在创建对象后,必须有值。赋值时机:
可在属性定义上赋予初始值
public final class class_Abstract { public final String s1 = "aaaa"; }可在类的构造方法中赋值
public final class class_Abstract { final String s1; public class_Abstract(){ s1 = "aaaa"; } }
可在代码块中赋值
public final class class_Abstract { final String s1; { s1 = "aaa"; } }注意:一旦代码块中赋值后,就不能在构造方法中再次赋值,因为常量不能再次赋值,代码块比构造方法先运行。
2.3.2 修饰局部变量
当修饰局部变量时,局部变量需要先声明后赋值或者声明时赋值。
2.3.3 修饰方法参数
当修饰方法参数时,表示传入的参数无法更改
2.3.4 常量
在类中我们一般会定义变量,声明final修饰,视作常量;
项目中我们将经常出现的一个常数或者字符串,不希望在过程中改变的,我们可以定义为常量。
常量定义时单词全大写,多个单词间用下划线隔开。
在java中有一些提供的常量,例如Math.PI
import static java.lang.Math;
public final class class_Abstract {
public void aa(){
System.out.println(Math.PI);
}
}
三、static
static:静态的
3.1 修饰属性
表示该属性为静态属性,也称为类属性。
同一个类中共享一个类属性空间(所有对象使用的同一个类属性),也可以用对象操作,但是不推荐。
注意:不能修饰局部变量,不需创建对象就可使用类属性,创建对象也可使用类属性。
public class Demo {
public static void main(String[] args) {
//类属性可以用对象调用也可以用类调用
System.out.println(A.name);
A a = new A();
System.out.println(a.name);
//因为类属性共享一个内存空间,所以使用对象修改类属性值,所有调用类属性都会改变
a.name = "修改后的类属性";
System.out.println(a.name);
System.out.println(A.name);
}
}
public class A {
static String name = "我是类属性";
}
3.2 修饰方法
表示为静态方法,也称类方法。
可以直接使用类名调用,也可创建对象调用。
注意:
静态方法不需创建对象就可使用;非静态方法需要创建对象调用
静态方法可以调用静态的方法和属性,不能调用非静态的方法和属性
非静态方法可以调用静态方法和属性,也可调用非静态的方法和属性;
静态方法不能使用this和super修饰,因为静态方法不用创建对象,this和super需要创建对象使用。
静态方法可以被继承,但是不能重写,所以也无法多态。
public class A {
static String name = "我是类属性";
String name1 = "我不是类属性";
static void S1(){
System.out.println(name);
// System.out.println(name1);//会报错,因为name1不是静态属性
}
//非静态方法可以使用所有属性
public void S2(){
System.out.println(name);
System.out.println(name1);
}
}
3.3 修饰代码块
3.3.1 动态代码块
类中由一对大括号组成的代码块称为动态代码块,创建对象时执行,可执行多次,每次创建对象都会执行。
执行流程:
初始化属性
执行动态代码块
执行构造方法
public class Demo {
public static void main(String[] args) {
new A();
}
}
public class A {
String name = "我是属性";
{
//将name放到此处,可以看出执行动态代码块前是否先初始化属性,否则会报错
System.out.println(name);
System.out.println("我是动态代码块");
}
public A(){
System.out.println("我是构造方法");
}
//我是属性
//我是动态代码块
//我是构造方法
}
3.3.2 静态代码块
static关键字修饰的代码块为静态代码块,类加载时执行,只执行一次。
在创建对象时会加载类
类加载:将类信息加载到方法区,以便得到对象创建时所需得空间大小,方便创建对象。
执行流程:
静态属性
静态代码块
实例属性
执行动态代码块
执行构造方法
public class Demo {
public static void main(String[] args) {
new A();
//我是静态属性
//我是静态代码块
//我是实例属性
//我是动态代码块
//我是构造方法
}
}
public class A {
String name = "我是实例属性";
static String name1 = "我是静态属性";
{
//将name放到此处,可以看出执行动态代码块前是否先初始化属性,否则会报错
System.out.println(name);
System.out.println("我是动态代码块");
}
{
//将name放到此处,可以看出执行动态代码块前是否先初始化属性,否则会报错
System.out.println(name1);
System.out.println("我是静态代码块");
}
public A(){
System.out.println("我是构造方法");
}
}
3.4 继承时的加载顺序
面试题:当A继承了B类,那么创建A对象,他们之中的加载顺序是什么样的??
加载流程:
-
父类静态属性
-
父类静态代码块
-
子类静态属性
-
子类静态代码块
-
父类实例属性
-
父类动态代码块
-
父类构造方法
-
子类实例属性
-
子类动态代码块
-
子类构造方法
由上执行流程可知,为什么类方法无法调用非静态属性。
public class Demo {
public static void main(String[] args) {
new A();
//我是父类静态属性
//我是父类静态代码块
//我是子类静态属性
//我是子类静态代码块
//我是父类实例属性
//我是父类动态代码块
//我是父类构造方法
//我是子类实例属性
//我是子类动态代码块
//我是子类构造方法
}
}
public class A extends B{
String name = "我是子类实例属性";
static String name1 = "我是子类静态属性";
{
//将name放到此处,可以看出执行动态代码块前是否先初始化属性,否则会报错
System.out.println(name);
System.out.println("我是子类动态代码块");
}
static {
//将name放到此处,可以看出执行动态代码块前是否先初始化属性,否则会报错
System.out.println(name1);
System.out.println("我是子类静态代码块");
}
public A(){
System.out.println("我是子类构造方法");
}
}
public class B {
String n1 = "我是父类实例属性";
static String n2 = "我是父类静态属性";
{
//将name放到此处,可以看出执行动态代码块前是否先初始化属性,否则会报错
System.out.println(n1);
System.out.println("我是父类动态代码块");
}
static {
//将name放到此处,可以看出执行动态代码块前是否先初始化属性,否则会报错
System.out.println(n2);
System.out.println("我是父类静态代码块");
}
public B(){
System.out.println("我是父类构造方法");
}
}


