java中的静态,抽象,接口,单例设计模式

静态 (实现属性方法共享)

抽象(一个类可能要继承多个父类)

内部类(类的内部还有类)

静态属性

静态属性是属于类的,可以直接使用类名来访问,也可以使用对象访问

非静态属性,是属于对象的,一定要使用对象来访问,没有其他方式!

静态属性,是属于类的,并且是这个类所有对象共享的

静态属性的存储位置:
类中的静态属性,跟随着类,一起保存在内存中的方法区。

当创建对象的时候,对象中只会保存类中定义的非静态属性的信息,而静态属性是不会进入到对象中的。

静态属性的初始化:
无论是静态属性还是非静态属性,都必须进行初始化后才能使用,要么是系统给属性初始化赋默认值,
要么是我们自己手动给属性赋值。
属性的初始化时间:
非静态属性:创建对象后,系统会自动给对象中的非静态属性做初始化赋默认值,也正是因为这个原因,非静态属性只有在创建对象后,使用对象才能方法
静态属性:类加载到内存中(方法区)的时候,系统就会给类中的 静态属性做初始化赋默认值,所以,即使还没有创建对象,只要这个类加载到了内存,就可以直接使用类名来访问静态属性,因为这个时候静态属性已经完成了初始化赋默认值的操作。

静态方法可以被继承,但是不能被重写(但是可以写这个名字的方法(名字参数可以一样))

静态方法中,不能访问this

静态代码块,也叫做静态初始化代码块,它的作用就是给类中的静态属性做初始化的

静态代码块的执行时刻:
由于静态代码块没有名字,我们并不能主动调用,它会在类加载的时候,自动执行。
所以静态代码块,可以更早的给类中的静态属性,进行初始化赋值操作。
并且,静态代码块只会自动被执行一次,因为JVM在一次运行中,对一个类只会加载一次!

public class Demo {
	public static int num;
	static{
		num = 10;
	}
}

public static void main(String[] args){
	System.out.println(Demo.num);//输出结果为 10
}

匿名代码块:
和静态代码块类似的,还有一种非静态代码块,也叫做匿名代码块,它的作用是给非静态属性做初始化操作

匿名代码块执行的时刻: 由于匿名代码块没有名字,我们并不能主动调用,它会在创建对象的时候,构造器执行之前,自动执行。 并且每次创建对象之前,匿名代码块都会被自动执行。

public class Demo {
	public int num;
	{
		num = 10;
	}
}

public static void main(String[] args){
	Demo demo = new Demo();
	System.out.println(demo.num);//输出结果为 10
}
public class Demo {
	static {
		System.out.println("静态代码块执行");
	}
	{
		System.out.println("匿名代码块执行");
	}
	public Demo(){
		System.out.println("构造器执行");
	}
}

public static void main(String[] args){
	new Demo();
	new Demo();
}
//输出结果为:
静态代码块执行
匿名代码块执行
构造器执行

创建和初始化对象的过程:
Student s = new Student();
以这句代码为例进行说明:
对Student类进行类加载,同时初始化类中静态的属性赋默认值,给静态方法分配内存空间
执行类中的静态代码块
堆区中分配对象的内存空间,同时初始化对象中的非静态的属性赋默认值
调用Student的父类构造器
对Student中的属性进行显示赋值,例如 public int age = 20;
执行匿名代码块
执行构造器代码
=号赋值操作,把对象的内存地址赋给变量s

public class Person{
	private String name = "zs";
	public Person() {
		System.out.println("Person构造器");
		print();
	}
	public void print(){
		System.out.println("Person print方法: name = "+name);
	}
}

class Student extends Person{
	private String name = "tom";
	{
		System.out.println("Student匿名代码块");
	}
	static{
		System.out.println("Student静态代码块");
	}
	public Student(){
		System.out.println("Student构造器");
	}
	public void print(){
		System.out.println("student print方法: name = "+name);
	}
	public static void main(String[] args) {
		new Student();
	}
}

结果

Student静态代码块

Person构造器

student print方法: name = null

Student匿名代码块

Student构造器

注意1,子类重写父类的方法,在创建子类对象的过程中,默认调用的一定是子类中重写后的方法
注意2,非静态属性的显示赋值,是在 父类构造器执行结束之后 和 子类中的匿名代码块执行之前的时候
注意3,以上代码中,因为方法的重写,会调用子类中重写后的print方法,同时该方法恰好是在父类构造器执行中调用的,而这个时候子类中的name属性还没有进行显示赋值,所以是输出结果为null
注意4,如果此时在子类的匿名代码块中也输出name的值,那么就会显示tom,因为已经完成了属性的显示赋值

静态导入

import 。。。。。

final

用final修饰的类不能被继承,也就是说这个类是没有子类的。

用final修饰的方法可以被子类继承,但是不能被子类重写。

用final修饰的变量就变成了常量,并且它只能被赋一次值,第二次赋值就会报错

用static声明的final变量不会默认初始化,所以必须自己赋值,否则会报错(可在静态代码块里赋值,非静态的可在匿名块赋值)(static默认初始化后会赋初值,会导致后面的赋值没有意义)

常量命名一般全部大写

抽象

abstract

abstract修饰符,可以修饰类、方法

如果abstract修饰方法,那么该方法就是抽象方法。

抽象方法的特点:

只有方法的声明 没有方法的实现

如果abstract修饰类,那么该类就是抽象类。

抽象类和非抽象类的区别:
抽象类使用了abstract修饰符,而非抽象类没有使用
抽象类中可以编写抽象方法,而非抽象类中不能编写抽象方法
抽象类不能进行实例化创建对象,而非抽象类可以实例化创建对象

抽象类是用来被子类继承的,子类继承抽象类,并且实现抽象类中的抽象方法。
所以,当前我们遇到一个抽象类的时候,这个类肯定需要被继承,然后实现里面的抽象方法,或者重写里面的普通方法。
注意,实现父类中的抽象方法 和 重写父类中的普通方法,只是说法不同,但是它们的语法要求,操作方式完全是一样的,可以直接把实现抽象方法当做重写方法来看。

抽象类不实例化创建对象,那么抽象类中是否有构造器?

有构造器,这个构造器是让子类调用的,子类继承父类,子类创建对象的时候,会先调用父类的构造器

子类继承抽象父类,子类可以选择实现父类中所有的抽象方法,如果有任何一个抽象方法没有被子类实现,那么这个子类也要将自己声明为抽象类,那么这个子类也就只能等待,再来一个子类继承自己,去实现剩余没有实现的抽象方法,直到所有抽象方法都被实现为止。

抽象类可以没有抽象方法(构造器)但是定义了抽象方法的类必须是抽象类

接口interface (定义出来的目的就是为了被实现)

引用数据类型:类、数组、接口

接口是除了类和数组之外,另外一种引用数据类型
接口和类不同,类的内部封装了成员变量、构造方法和成员方法,而接口的内部主要就是封装了方法和静态常量。
接口的定义和类很类似,但是接口需要使用 interface 关键字来定义
接口最终也会被编译成.class文件,但一定要明确接口并不是类,而是另外一种引用数据类型

//使用interface关键字来定义接口
public interface Action {//特殊的父类
	//接口中的静态常量
	public static final String OPS_MODE = "auto";
	//接口中的抽象方法
	public void start();
	//接口的抽象方法
    public void stop();
}

注意1, 定义类使用关键字 class ,定义接口使用关键字 interface
注意2,接口中的属性都是公共的静态常量,且常量的名字一般需要全大写
注意3,接口中的方法都是抽象方法
注意:JDK8中,还允许在接口中编写静态方法和默认方法
注意:JDK9中,还允许在接口中编写私有方法
注意4,接口的中抽象方法,不需要使用 abstract 修饰符,因为接口中的方法默认就是抽象方法

接口里面的属性,默认就是public static final修饰的 (常量)

接口里面的方法,默认就是public abstract修饰的

所以这些都可以省去不写的

接口中没有构造器

接口实现:

类和类之间的关系是继承,类和接口之间的关系是实现:一个类实现了一个或多个接口(特殊的继承)

接口和类不同,类可以实例化创建对象,而接口不能创建对象,只能让其他类来实现。
一个类实现了一个接口,那么该类可以称为这个接口的实现类。类实现一个接口 和 类继承一个父类 的效果类似,格式相仿,只是关键字不同,实现使用 implements 关键字,而继承使用的是extends关键
字。
一个类实现了接口,那么就要实现接口中所有的抽象方法否则这个类自己就必须声明为抽象类

public interface Action {
	void run();
	void sayHello();//接口中的普通方法都是抽象方法
}

//类实现接口,没有实现接口中的抽象方法,那么这个类就必须声明为抽象类
abstract class Student1 implements Action{
}

//类实现接口,并且实现了接口中所有的抽象方法
class Student2 implements Action{
	public void run(){
	//...
	}
	public void sayHello(){
	//...
	}
}

一个类可以实现多个接口,实现了多个接口,那么就需要把这多个接口中的抽象想法全都实现

public interface Action {
	void run();
	void sayHello();
}
public interface Mark{
	void star();
}
public interface Action {
	void run();
	void sayHello();
}
public interface Mark{
	void star();
}

所以java被称为单继承多实现

接口之间也可以继承,并且可以多继承

//实现该接口的类,将具有run的功能
public interface Runable {
	void run();
}

//实现该接口的类,将具有fly的功能
interface Flyable{
	void fly();
}

//实现该接口的类,将具有run的功能,fly的功能,以及Action接口独有的doSomething功能
interface Action extends Runable,Flyable{
	void doSomething();
}

//实现类,实现Action接口,就必须要实现Action及其父接口中的所有抽象方法
class Demo implements Action{
	@Override
	public void run() {
	}
	@Override
	public void fly() {
	}
	@Override
	public void doSomething() {
	}
}

如何让开发人员,一定能按照我们的预先设计好的方法,去编写代码?

面向接口编程:

访问控制

修饰符:public > protected > default > private

在这里插入图片描述

单例(设计模式):

​ 不管任何时候,通过这个类获取对象时,永远拿到的是同一个对象

class A{
    //创建A
    private static A instance= new A();
    
    //public A(){}
	private A(){}
	
    //提供方法获取创建的对象
    public static A tt(){
        return instance;
	}
}

class B{
	
}

public class Main {
	public static void main(String[] args) {
		A a1 = A.tt();
		A a2 = A.tt();
		B b1 = new B();
		B b2 = new B();
		System.out.println(a1.equals(a2));
		System.out.println(b1.equals(b2));
	}
}

true
false
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值