1.关键字:static
应用场景:当我们需要给某个类的属性设定一个默认值(比如中国人的class,其中所有对象的country属性值都应该为“中国”)
关于static:
-
静态
-
可以修饰属性、方法、代码块、内部类(不能修饰构造器)
-
修饰属性:静态属性(静态变量、类变量),即当修改某一个对象的静态属性时,其他对象的此静态属性值也是修改后的结果。
public class StaticTest { public static void main(String[] args) { Chinese p1 = new Chinese(); p1.country = "CHN"; Chinese p2 = new Chinese(); System.out.println(p2.country);//虽然p2的country未赋值,但结果为“CHN” p2.country = "CHINA"; System.out.println(p1.country);//此时p1的country值也变成“CHINA” } } class Chinese{ int age; String name; static String country; }- 为什么叫类变量:静态变量是随着class的加载而加载,可以通过“类名.静态变量”的方式直接调用。(因此静态变量的创建早于对象的创建)
- 由于类只加载一次,因此静态变量在内存中只存在一份:存在方法区的静态域中。
-
修饰方法:静态方法
- 同静态属性:随着class的加载而加载,可以通过“类名.静态方法”的方式直接调用。
- 静态方法中:只能调用静态的方法或属性(生命周期)。不能使用this、super关键字。
-
2.类的成员之四:代码块
-
代码块(初始化块)作用:用来初始化类、对象。
-
只能用static修饰。
-
static代码块:
- 随着类的加载而执行,且只执行1次;
- 作用:初始化类的信息。
- 如果一个类中定义了多个static代码块,按定义的先后顺序执行。
- 先执行static代码块,再执行非static。
- 只能调用static属性、方法。
-
非static代码块:
-
随着对象的创建而执行,每创建一个对象就执行一次代码块。
-
可以在对象的创建时,对其属性进行初始化。
-
定义多个非static代码块,也是按先后顺序执行。
-
static/非static属性、方法都可调用。
-
-
package com.coderLeo.study;
public class BlockTest {
public static void main(String[] args) {
String desc = Person.desc;
/*执行完上一句,就显示:hello, static code block!
* 说明static代码块,是随着类的加载而执行
* */
Person p1 = new Person();
/* 显示:hello, nostatic code block!
* 说明随着对象的创建而执行
* */
Person.info();
//只执行I am a funny man!
//说明静态代码块随着类的加载,只执行1次
}
}
class Person{
//attribute
int age;
String name;
static String desc = "我是一个人";
//constructor
public Person(){
}
public Person(int age, String name){
this.age = age;
this.name = name;
}
//static code block
static{
System.out.println("hello, static code block!");
info();//可以调用static方法
//this.age = 10; //非static不能调用
}
//nostatic code block
{
this.age = 1;//nostatic的block,初始化对象的属性。
System.out.println("hello, nostatic code block!");
}
//method
public void Eat(){
System.out.println("I am eating!");
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
static public void info(){
System.out.println("I am a funny man!");
}
}
- 关于代码块的执行顺序:由父类到子类,static先行。
- 代码块的变量赋值顺序:与显式赋值和代码块赋值的先后顺序有关,即谁在前谁先赋值。
3.关键字:final
final用来修饰:class、method、variable
-
修饰class:final class 类名。此时
- 这个class不能被其他类继承。比如:String类、StringBuffer类、System类
-
修饰method:权限符后+final
- 表示method不可被重写(override)。有:Object类中的getClass。
-
修饰variable:此时的”variable“是一个constant
-
修饰属性:可以考虑显示初始化、代码块、构造器。
-
修饰局部变量:constant
- 方法体内部:不能修改。
- 形参:调用方法时给常量形参赋值后,只能在方法内调用,不能修改。
-
-
static final xx:修饰属性表示全局常量。直接用类调用(类名.xx)
4.抽象类和抽象方法
关键字:abstract,用来修饰class、method。
对于class:
- 一旦加上abstract,不可实例化。
- 但抽象类中仍然有构造器。
对于method:
- 只有方法声明,无方法体:权限 abstract 返回值 方法名(形参)
- 包含抽象方法的class一定是抽象类。
- 子类重写父类中所有的抽象方法后,此子类方可实例化。否则,该子类也是抽象类(也应该加上abstract关键字)
使用时注意:
- 不能用来修饰属性、构造器、私有方法、静态方法、final方法、final类
抽象类的匿名对象:
public class PersonTest {
public static void main(String[] args) {
//创建匿名子类的对象:p
Person p = new Person(){
@Override
public void eat(){
System.out.println("people is eating...");
}
};
/*理解:由于Person类是abstract,不能实例化对象。因此这里创建的是Person子类,这个子类是无名的,因此叫匿名子类
* 并且随后重写了其中的抽象方法eat()
* 然后用多态的方式以Person p来接收这个Person子类
*/
method(p);//people is eating...
//匿名子类的匿名对象
method(new Person(){
@Override
public void eat(){
System.out.println("people have eaten");
}
});//people have eaten
}
public static void method(Person p){
p.eat();
}
}
abstract class Person {
String name;
int age;
public Person(){}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public abstract void eat();
public void walk(){
System.out.println("people walk...");
}
}
5.接口(Interface)
关键字:interface。java中class和interface是并列关系。
定义接口:定义接口的成员
- jdk7及以前:只能定义全局常量(public static final)和抽象方法(public abstract)
- jdk8:还可以定义静态方法、默认方法
- 不能定义构造器
java中,让class去实现(implements) 接口:
- 若实现类重写了所有接口中的抽象方法,则此实现类可以实例化。
- 否则该实现类仍然是抽象类。
- java类可以实现多个接口,格式:class 类名 extends 父类名 implements 接口1,接口2...
接口与接口之间可以继承,而且可以多继承。
一个例子:
public class InterfaceTest {
public static void main(String[] args) {
Plane test = new Plane();
test.fly();//engine fly
System.out.println(test.MAX_SPEED);//7900
}
}
interface Flyable{
//全局常量
public static final int MAX_SPEED = 7900;
int MIN_SPEED = 1;//public static final可以省略,interface默认是这样
//抽象方法
public abstract void fly();
void stop();//也是可以省略public abstract
}
interface Offensive{
public abstract void attack();
}
class Plane implements Flyable{
@Override
public void fly() {
System.out.println("engine fly");
}
@Override
public void stop() {
System.out.println("stop by engine");
}
}
abstract class Kite implements Flyable{
}
class Bullet extends Object implements Flyable, Offensive, CC{
@Override
public void attack() {
}
@Override
public void fly() {
}
@Override
public void stop() {
}
//Bullet继承了CC,CC多继承AA、BB,Bullet类就要实现这两个抽象方法
@Override
public void method1() {
}
@Override
public void method2() {
}
}
interface AA{
void method1();
}
interface BB{
void method2();
}
interface CC extends AA,BB{//CC多继承AA、BB
}
还有几个重要的点:
-
接口满足多态性
-
接口定义了一种规范
-
创建接口匿名实现类的对象:
- 非匿名实现类的非匿名对象
- 非匿名实现类的匿名对象
- 匿名实现类的非匿名对象
- 匿名实现类的匿名对象
public class USBTest {
public static void main(String[] args) {
Computer test = new Computer();
//造实现类的对象,这里有Flash、Printer实现USB。
Flash flash = new Flash();
//①非匿名实现类(Flash)的非匿名对象(flash)
//1.(对应上述第1条)Computer的transferData虽然声明的是USB形参,但出入的是其实现类Flash,体现了接口的多态性,而且这是必须的。
test.transferData(flash);
/*FLASH starts working...
具体的传输细节
FLASH stop working...
*/
//②非匿名实现类(Printer)的匿名对象(new出来的这个对象没名)
test.transferData(new Printer());
//③匿名实现类(USB的实现类没名,在这里创建时直接重写了实现的方法)的非匿名对象(phone)
USB phone = new USB(){
@Override
public void start() {
System.out.println("phone start working");
}
@Override
public void stop() {
System.out.println("phone stop working");
}
};
test.transferData(phone);
//④匿名实现类的匿名对象
test.transferData(new USB(){
@Override
public void start() {
System.out.println("Laptop start working");
}
@Override
public void stop() {
System.out.println("Laptop stop working");
}
});
}
}
class Computer{
//参数为USB接口,但是接口本身不能实例化,因此实际传入的是其实现类的对象
public void transferData(USB usb){
usb.start();
System.out.println("具体的传输细节");
usb.stop();
}
}
//定义接口USB。2.(第2条)定义了一种规范,就是每个想要用USB接口的都得遵循这里的start、stop
interface USB{
void start();
void stop();
}
//Flash类实现USB
class Flash implements USB{
@Override
public void start() {
System.out.println("FLASH starts working...");
}
@Override
public void stop() {
System.out.println("FLASH stop working...");
}
}
//Printer实现USB
class Printer implements USB{
@Override
public void start() {
System.out.println("Printer starts working...");
}
@Override
public void stop() {
System.out.println("Printer stop working...");
}
}