面向对象(下)

news2024/11/19 10:18:36

目录

  • 01、static
    • 1.1、static的使用
    • 1.2、static应用举例
    • 1.3、单例(Singleton)设计模式
  • 02、main方法的语法
  • 03、类的成员之四:代码块
  • 04、关键字:final
  • 05、抽象类与抽象方法
    • 5.1、多态的应用:模板方法设计模式(TemplateMethod)
  • 06、接口(interface)
    • 6.1、概述
    • 6.2、接口的应用:代理模式(Proxy)
  • 07、Java 8 中关于接口的改进

01、static

我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份。

1.1、static的使用

static 关键字的使用
1.static:静态的。
2.static 可以用来修饰:属性、方法、代码块、内部类。
3.使用 static 修饰属性:静态变量(或类变量)。
  3.1 属性:是否使用 static 修饰,又分为:静态属性 VS 非静态属性(实例变量)
     实例变量:我们创建了类的多个对象,每个对象都独立的拥有了一套类中的非静态属性。当修改其中一个非静态属性时,不会导致其他对象中同样的属性值的修饰。
    静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过静态变量去修改某一个变量时,会导致其他对象调用此静态变量时,是修改过的
  3.2 static 修饰属性的其他说明:
    ① 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
    ② 静态变量的加载要早于对象的创建。
    ③ 由于类只会加载一次,则静态变量在内存中也只会存在一次。存在方法区的静态域中。
    ④   类变量  实例变量
    类    yes    no
    对象  yes    yes
  3.3 静态属性举例:System.out ;  Math.PI;
4.使用 static 修饰方法:静态方法
  ① 随着类的加载而加载,可以通过"类.静态方法"的方式调用
  ②    方法    非静态方法
  类    yes       no
  对象  yes       yes
  ③ 静态方法中,只能调用静态的方法或属性
     非静态的方法中,可以调用所有的方法或属性
5.static 注意点:
  5.1 在静态的方法内,不能使用 this 关键字、super 关键字
  5.2 关于静态属性和静态方法的使用,大家从生命周期的角度去理解。
6.开发中,如何确定一个属性是否需要声明 static 的?
  》 属性是可以被多个对象所共享的,不会随着对象的不同而不同的。
  》 类中的常量也常常声明为 static
  开发中,如何确定一个方法是否要声明为 static 的?
  》 操作静态属性的方法,通常设置为 static 的
  》 工具类中的方法,习惯上声明为 static 的。比如:Math、Arrays、Collections
在这里插入图片描述

public class StaticTest {
	public static void main(String[] args) {
		
		Chinese.nation = "中国";
		
		Chinese c1 = new Chinese();
		c1.name = "姚明";
		c1.age = 40;
		c1.nation = "CHN";
		
		Chinese c2 = new Chinese();
		c2.name = "马龙";
		c2.age = 30;
		c2.nation = "CHINA";
		
		System.out.println(c1.nation); 
		
		//编译不通过
//		Chinese.name = "张继科";
		
	}
}
//中国人
class Chinese{
	
	String name;
	int age;
	static String nation;
}

static修饰方法

public class StaticTest {
	public static void main(String[] args) {
		
		Chinese.nation = "中国";
		
		Chinese c1 = new Chinese();
		
		//编译不通过
//		Chinese.name = "张继科";
		
		c1.eat();
		
		Chinese.show();
		//编译不通过
//		chinese.eat();
//		Chinese.info();
	}
}
//中国人
class Chinese{
	
	String name;
	int age;
	static String nation;
	
	public void eat(){
		System.out.println("中国人吃中餐");
		//调用非静态结构
		this.info();
		System.out.println("name : " + name);
		//调用静态结构
		walk();
		System.out.println("nation : " + Chinese.nation);
	}
	
	public static void show(){
		System.out.println("我是一个中国人!");
//		eat();
//		name = "Tom";
		//可以调用静态的结构
		System.out.println(Chinese.nation);
		walk();
	}
	
	public void info(){
		System.out.println("name : " + name + ",age : " + age);
	}
	
	public static void walk(){
		
	}
}

1.2、static应用举例

//static 关键字的应用
public class CircleTest {
	public static void main(String[] args) {
		
		Circle c1 = new Circle();
		
		Circle c2 = new Circle();
		
		Circle c3 = new Circle();
		
		System.out.println("c1 的 ID:" + c1.getId());
		System.out.println("c2 的 ID:" + c2.getId());
		System.out.println("c3 的 ID:" + c3.getId());
		
		System.out.println("创建圆的个数: " + Circle.getTotal());
		
	}
	
}

class Circle{
	
	private double radius;
	private int id;	//需要自动赋值
	
	public Circle(){
		id = init++;
		total++;
	}
	
	public Circle(double radius){
		this();
		//或
//		id = init++;
//		total++;
		this.radius = radius;
	}
	
	private static int total;//记录创建圆的个数
	private static int init = 1001;//static 声明的属性被所有对象所共享
	
	public double findArea(){
		return 3.14 * radius * radius;
	}

	public double getRadius() {
		return radius;
	}

	public void setRadius(double radius) {
		this.radius = radius;
	}

	public int getId() {
		return id;
	}

	public static int getTotal() {
		return total;
	}
	
}

1.3、单例(Singleton)设计模式

设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模免去我们自己再思考和摸索。就像是经典的棋谱,不同的棋局,我们用不同的棋谱。”套路”

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例并且该类只提供一个取得其对象实例的方法。如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为 private,这样,就不能用 new 操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。

1、单例模式的饿汉式

/*
 * 单例设计模式:
 * 1.所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
 *  
 * 2.如何实现?
 *   饿汉式	VS	懒汉式
 * 
 * 3.区分饿汉式和懒汉式。
 * 	   饿汉式:坏处:对象加载时间过长。
 * 	 	       好处:饿汉式是线程安全的。
 * 
 *   懒汉式:好处:延迟对象的创建。
 * 		       坏处:目前的写法,会线程不安全。---》到多线程内容时,再修改
 */
public class SingletonTest {
	public static void main(String[] args) {
//		Bank bank1 = new Bank(); 
//		Bank bank2 = new Bank(); 
		
		Bank bank1 = Bank.getInstance();
		Bank bank2 = Bank.getInstance();
		
		System.out.println(bank1 == bank2);
		
	}
}

//单例的饿汉式
class Bank{
	
	//1.私有化类的构造器
	private Bank(){
		
	}
	
	//2.内部创见类的对象
	//4.要求此对象也必须声明为静态的
	private static Bank instance = new Bank();
	
	//3.提供公共的静态的方法,返回类的对象。
	public static Bank getInstance(){
		return instance;
	}
}

2、单例模式的懒汉式

/*
 * 单例的懒汉式实现
 * 
 */
public class SingletonTest2 {
	public static void main(String[] args) {
		
		Order order1 = Order.getInstance();
		Order order2 = Order.getInstance();
		
		System.out.println(order1 == order2);
	}
}
class Order{
	//1.私有化类的构造器
	private Order(){
		
	}
	
	//2.声明当前类对象,没有初始化。
	//此对象也必须声明为 static 的
	private static Order instance = null;
	
	//3.声明 public、static 的返回当前类对象的方法
	public static Order getInstance(){
		if(instance == null){
			instance = new Order();			
		}
		return instance;
	}
}

3、单例模式的优点

由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
在这里插入图片描述

4、单例(Singleton)设计模式-应用场景

  • 网站的计数器,一般也是单例模式实现,否则难以同步。
  • 应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
  • 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
  • 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取。
  • Application也是单例的典型应用
  • Windows 的Task Manager (任务管理器)就是很典型的单例模式
  • Windows 的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

02、main方法的语法

由于 Java 虚拟机需要调用类的 main()方法,所以该方法的访问权限必须是 public,又因为 Java 虚拟机在执行 main()方法时不必创建对象,所以该方法必须是 static 的,该方法接收一个 String 类型的数组参数,该数组中保存执行 Java 命令时传递给所运行的类的参数。

又因为 main() 方法是静态的,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,这种情况,我们在之前的例子中多次碰到。

/*
 * main()方法的使用说明
 * 1.main()方法作为程序的入口;
 * 2.main()方法也是一个普通的静态方法
 * 3.main()方法也可以作为我们与控制台交互的方式。(之前,使用 Scanner)
 * 
 * 
 */
public class MainTest {
	public static void main(String[] args) {	//入口
		
		Main.main(new String[100]);
		
		MainTest test = new MainTest();
		test.show();
	}
	
	public void show(){
		
	}
}

class Main{
	public static void main(String[] args) {
		args = new String[100];
		for(int i = 0;i < args.length;i++){
			args[i] = "args_" + i;
			System.out.println(args[i]);
		}
	}
}

03、类的成员之四:代码块

代码块(或初始化块)
  1.代码块的作用:用来初始化类、对象的
  2.代码块如果有修饰的话,只能使用 static
  3.分类:静态代码块 vs 非静态代码块
  4.静态代码块

  • 内部可以有输出语句
  • 随着类的加载而执行,而且只执行一次
  • 作用:初始化类的信息
  • 如果一个类中,定义了多个静态代码块,则按照声明的先后顺序执行
  • 静态代码块的执行,优先于非静态代码块的执行
  • 静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构

  5.非静态代码块

  • 内部可以有输出语句
  • 随着对象的创建而执行
  • 每创建一个对象,就执行一次非静态代码块。
  • 作用:可以在创建对象时,对对象的属性等进行初始化。
  • 如果一个类中,定义了多个非静态代码块,则按照声明的先后顺序执行
  • 非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法。

  对属性可以赋值的位置:
   ①默认初始化
   ②显式初始化
   ③构造器中初始化
   ④有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值。
   ⑤在代码块中赋值
在这里插入图片描述

public class BlockTest {
	public static void main(String[] args) {
		
		String desc = Person.desc;
		System.out.println(desc);
		
		Person p1 = new Person();
		Person p2 = new Person();
		System.out.println(p1.age);
		
		Person.info();
	}
}

class Person{
	//属性
	String name;
	int age;
	static String desc = "我是一个青年";
	
	//构造器
	public Person(){
		
	}
	
	//static 的代码块
	static{
		System.out.println("hello,static block-1");
		//调用静态结构
		desc = "我是一个爱小说的人";
		info();
		//不能调用非静态结构
//		eat();
//		name = "Tom";
	}
	
	static{
		System.out.println("hello,static block-2");
	}
	
	//非 static 的代码块
	{
		System.out.println("hello,block-2");
	}
	{
		System.out.println("hello,block-1");
		//调用非静态结构
		age = 1;
		eat();
		//调用静态结构
		desc = "我是一个爱小说的人 1";
		info();
	}	
	
	//方法
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	public void eat(){
		System.out.println("吃饭");
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	public static void info(){
		System.out.println("我是一个快乐的人。");
	}
	
}

静态初始化块举例

总结:由父类到子类,静态先行

class Root{
	static{
		System.out.println("Root 的静态初始化块");
	}
	{
		System.out.println("Root 的普通初始化块");
	}
	public Root(){
		System.out.println("Root 的无参数的构造器");
	}
}
class Mid extends Root{
	static{
		System.out.println("Mid 的静态初始化块");
	}
	{
		System.out.println("Mid 的普通初始化块");
	}
	public Mid(){
		System.out.println("Mid 的无参数的构造器");
	}
	public Mid(String msg){
		//通过 this 调用同一类中重载的构造器
		this();
		System.out.println("Mid 的带参数构造器,其参数值:"
			+ msg);
	}
}
class Leaf extends Mid{
	static{
		System.out.println("Leaf 的静态初始化块");
	}
	{
		System.out.println("Leaf 的普通初始化块");
	}	
	public Leaf(){
		//通过 super 调用父类中有一个字符串参数的构造器
		super("尚硅谷");
		System.out.println("Leaf 的构造器");
	}
}
public class LeafTest{
	public static void main(String[] args){
		new Leaf(); 
		//new Leaf();
	}
}

在这里插入图片描述

04、关键字:final

1.final可以用来修饰的结构:类、方法、变量
2.final用来修饰一个类:此类不能被其他类所继承。比如:String类、System类、StringBuffer类
3.final修饰一个方法:final标记的方法不能被子类重写。比如:Object类中的getClass()。
4.final用来修饰变量:此时的"变量"(成员变量或局部变量)就是一个常量。名称大写,且只能被赋值一次。
  4.1 final修饰属性,可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化
  4.2 final修饰局部变量:
    尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。
    一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。
static final 用来修饰:全局常量

public class FinalTest {
	
	final int WIDTH = 0;
	final int LEFT;
	final int RIGHT;
//	final int DOWN;
	
	{
		LEFT = 1;
	}
	
	public FinalTest(){
		RIGHT = 2;
	}
	
	public FinalTest(int n){
		RIGHT = n;
	}
	
//	public void setDown(int down){
//		this.DOWN = down;
//	}
	
	public void dowidth(){
//		width = 20;	//width cannot be resolved to a variable
	}
	
	public void show(){
		final int NUM = 10;	//常量
//		num += 20;
	}
	
	public void show(final int num){
		System.out.println(num);
	}
	
	public static void main(String[] args) {
		
		int num = 10;
		
		num = num + 5;
		
		FinalTest test = new FinalTest();
//		test.setDown(5);
		
		test.show(10);
	}
}

final class FianlA{
	
}

//class B extends FinalA{     //错误,不能被继承。
//	
//}

//class C extends String{
//	
//}

class AA{
	public final void show(){
		
	}
}

//class BB extends AA{	// 错误,不能被重写。
//	public void show(){
//		
//	}
//}

05、抽象类与抽象方法

随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类
在这里插入图片描述

 1.abstract:抽象的
 2.abstract 可以用来修饰的结构:类、方法
 3.abstract 修饰类:抽象类

  • 此类不能实例化
  • 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化全过程)
  • 开发中,都会提供抽象类的子类,让子类对象实例化,实现相关的操作

 4.abstract 修饰方法:抽象方法

  • 抽象方法,只有方法的声明,没有方法体。
  • 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法
  • 若子类重写了父类中所有的抽象方法,此子类方可实例化;若子类吗,没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰

abstract 使用上的注意点:
 1.abstract 不能用来修饰变量、代码块、构造器
 2.abstract 不能用来修饰私有方法、静态方法、final 的方法、final 的类。

public class AbstractTest {
	public static void main(String[] args) {
		//一旦 Person 类抽象了,就不可实例化
//		Person p1 = new Person();
//		p1.eat();
		
	}
}

abstract class Creature{
	public abstract void breath();
}

abstract class Person extends Creature{
	String name;
	int age;
	
	public Person(){
		
	}
	
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	//不是抽象方法
//	public void eat(){
//		System.out.println("人吃饭");
//	}
	
	//抽象方法
	public abstract void eat();
	
	public void walk(){
		System.out.println("人走路");
	}
}

class Student extends Person{
	public Student(String name,int age){
		super(name,age);
	}
	public void eat(){
		System.out.println("学生应该多吃有营养的。");
	}
	@Override
	public void breath() {
		System.out.println("学生应该呼吸新鲜的无雾霾空气");
	}
}

抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类

5.1、多态的应用:模板方法设计模式(TemplateMethod)

抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

解决的问题:

当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式

06、接口(interface)

6.1、概述

一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java 不支持多重继承。有了接口,就可以得到多重继承的效果。

另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又没有 is-a 的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打印机、扫描仪、摄像头、充电器、MP3 机、手机、数码相机、移动硬盘等都支持 USB 连接。

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要…则必须能…”的思想。继承是一个"是不是"的关系,而接口实现则是"能不能"的关系。

接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都要遵守。
在这里插入图片描述

接口(interface)是抽象方法和常量值定义的集合
接口的特点:

  • 用 interface 来定义。
  • 接口中的所有成员变量都默认是由 public static final 修饰的
  • 接口中的所有抽象方法都默认是由 public abstract 修饰的
  • 接口中没有构造器
  • 接口采用多继承机制。

 1.接口使用 interface 来定义。
 2.在 Java 中:接口和类是并列的两个结构
 3.如何去定义两个接口:定义接口中的成员
   3.1 JDK7 及以前:只能定义全局常量和抽象方法
      全局常量:public static final 的,但是书写中,可以省略不写。
      抽象方法:public abstract 的
   3.2 JDK8:除了全局常量和抽象方法之外,还可以定义静态方法、默认方法。
 4.接口中不能定义构造器!意味着接口不可以实例化。
 5.Java 开发中,接口通过让类去实现(implements)的方式来使用。如果实现类覆盖了接口中的所有方法,则此实现类就可以实例化;如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
 6.Java 类可以实现多个接口 -->弥补了 Java 单继承性的局限性
   格式:class AA extends BB implementd CC,DD,EE
 7.接口与接口之间是继承,而且可以多继承
 8.接口的具体使用,体现多态性
   接口的主要用途就是被实现类实现。(面向接口编程)

public class InterfaceTest {
	public static void main(String[] args) {
		System.out.println(Flayable.MAX_SPEED);
		System.out.println(Flayable.MIN_SPEED);
	}
}
interface Flayable{
	
	//全局变量
	public static final int MAX_SPEED = 7900;	
	int MIN_SPEED = 1;//省略了 public static final 
	
	//抽象方法
	public abstract void fly();
	
	void stop();//省略了 public abstract 
	//Interfaces cannot have constructors
//	public Flayable(){
//		
//	}	
}
interface Attackable{
	void attack();
}

class Plane implements Flayable{

	@Override
	public void fly() {
		System.out.println("飞机通过引擎起飞");
		
	}

	@Override
	public void stop() {
		System.out.println("驾驶员减速停止");
	}
	
}
abstract class Kite implements Flayable{

	@Override
	public void fly() {
		
	}
}

class Bullet extends Object implements Flayable,Attackable,CC{

	@Override
	public void attack() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void method1() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void method2() {
		// TODO Auto-generated method stub
		
	}
}

//*********************************
interface AA{
	void method1();
}
interface BB{
	void method2();
}
interface CC extends AA,BB{
	
}

举例

/*
 * 接口的使用
 * 1.接口使用上也满足多态性
 * 2.接口,实际上就是定义了一种规范
 * 3.开发中,体会面向接口编程!
 * 
 */
public class USBTest {
	public static void main(String[] args) {
		
		Computer com = new Computer();
		//1.创建了接口的非匿名实现类的非匿名对象
		Flash flash = new Flash();
		com.transferData(flash); 
		//2. 创建了接口的非匿名实现类的匿名对象
		com.transferData(new Printer());
		//3. 创建了接口的匿名实现类的非匿名对象
		USB phone = new USB(){

			@Override
			public void start() {
				System.out.println("手机开始工作");
			}

			@Override
			public void stop() {
				System.out.println("手机结束工作");
			}
			
		};
		com.transferData(phone);
		//4. 创建了接口的匿名实现类的匿名对象
		com.transferData(new USB(){
			@Override
			public void start() {
				System.out.println("mp3 开始工作");
			}

			@Override
			public void stop() {
				System.out.println("mp3 结束工作");
			}
		});
	}
}

class Computer{
	
	public void transferData(USB usb){//USB usb = new Flash();
		usb.start();
		
		System.out.println("具体传输数据的细节");
		
		usb.stop();
	}
	
}

interface USB{
	//常量:定义了长、宽
	void start();
	
	void stop();
}
class Flash implements USB{

	@Override
	public void start() {
		System.out.println("U 盘开始工作");
	}

	@Override
	public void stop() {
		System.out.println("U 盘结束工作");
	}
}
class Printer implements USB{
	@Override
	public void start() {
		System.out.println("打印机开启工作");
	}

	@Override
	public void stop() {
		System.out.println("打印机结束工作");
	}
	
}

6.2、接口的应用:代理模式(Proxy)

代理模式是 Java 开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
在这里插入图片描述

/*
 * 接口的应用:代理模式
 * 
 * 
 */
public class NetWorkTest {
	public static void main(String[] args) {
		
		Server server = new Server();
//		server.browse();
		ProxyServer proxyServer = new ProxyServer(server);
		
		proxyServer.browse();
	}
}
interface NetWork{
	public void browse();
	
}
//被代理类
class Server implements NetWork{


	@Override
	public void browse() {
		System.out.println("真实的服务器来访问网络");
	}
}
//代理类
class ProxyServer implements NetWork{
	
	private NetWork work;
	
	public ProxyServer(NetWork work){
		this.work = work;
	}
	
	public void check(){
		System.out.println("联网前的检查工作");
	}

	@Override
	public void browse() {
		check();
		
		work.browse();
	}
	
}

应用场景:

  • 安全代理:屏蔽对真实角色的直接访问。
  • 远程代理:通过代理类处理远程方法调用(RMI)
  • 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象

比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有 100MB,在打开文件时,不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用 proxy 来进行大图片的打开。

分类

  • 静态代理(静态定义代理类)
  • 动态代理(动态生成代理类)
    JDK 自带的动态代理,需要反射等知识
public class StaticProxyTest {

	public static void main(String[] args) {
		Proxy s = new Proxy(new RealStar());
		s.confer();
		s.signContract();
		s.bookTicket();
		s.sing();
		s.collectMoney();
	}
}

interface Star {
	void confer();// 面谈

	void signContract();// 签合同

	void bookTicket();// 订票

	void sing();// 唱歌

	void collectMoney();// 收钱
}
//被代理类
class RealStar implements Star {

	public void confer() {
	}

	public void signContract() {
	}

	public void bookTicket() {
	}

	public void sing() {
		System.out.println("明星:歌唱~~~");
	}

	public void collectMoney() {
	}
}

//代理类
class Proxy implements Star {
	private Star real;

	public Proxy(Star real) {
		this.real = real;
	}

	public void confer() {
		System.out.println("经纪人面谈");
	}

	public void signContract() {
		System.out.println("经纪人签合同");
	}

	public void bookTicket() {
		System.out.println("经纪人订票");
	}

	public void sing() {
		real.sing();
	}

	public void collectMoney() {
		System.out.println("经纪人收钱");
	}
}

07、Java 8 中关于接口的改进

Java 8 中,你可以为接口添加静态方法和默认方法。从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。

静态方法:

使用 static 关键字修饰。可以通过接口直接调用静态方法,并执行其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中找到像 Collection/Collections 或者 Path/Paths 这样成对的接口和类。

默认方法:

默认方法使用 default 关键字修饰。可以通过实现类对象来调用。我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。比如:java 8 API 中对 Collection、List、Comparator 等接口提供了丰富的默认方法。

/*
 * JDK8:除了全局常量和抽象方法之外,还可以定义静态方法、默认方法(略)。
 * 
 * 
 */
public interface CompareA {

	//静态方法
	public static void method1() {
		System.out.println("CompareA:西安");
	}
	
	//默认方法
	public default void method2(){
		System.out.println("CompareA:深圳");
	}
	
	default void method3(){
		System.out.println("CompareA:杭州");
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1521300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flink1.18.0 自定义函数 接收row类型的参数

比如sql中某字段类型 array<row<f1 string,f2 string,f3 string,f4 bigint>> 现在需要编写 tableFunction 需要接受的参数如上 解决方案 用户定义函数|阿帕奇弗林克 --- User-defined Functions | Apache Flink

C语言数据结构(7)——树、二叉树前言

欢迎来到博主的专栏——C语言数据结构 博主ID&#xff1a;代码小豪 文章目录 树二叉树特殊二叉树满二叉树完全二叉树 完全二叉树的存储结构 树 树是一个非线性的数据结构&#xff0c;由N个结点构成的集合。 树的各个结点由一个根结点联系起来&#xff0c;这个根节点没有前驱…

小球垂直跳动,C语言模拟重力加速度

位移公式 1、速度和时间关系&#xff1a; 2、位移和时间关系&#xff1a; 3、力和加速度关系&#xff1a; 4、空气阻力&#xff1a; 受理分析 以向下运动为正方向 1、向下运动整体受力&#xff0c;重力加空气阻力: 2、向上运动整理受力&#xff0c;重力减空气阻力&…

Apache zookeeper kafka 开启SASL安全认证

背景&#xff1a;我之前安装的kafka没有开启安全鉴权&#xff0c;在没有任何凭证的情况下都可以访问kafka。搜了一圈资料&#xff0c;发现有关于sasl、acl相关的&#xff0c;准备试试。 简介 Kafka是一个高吞吐量、分布式的发布-订阅消息系统。Kafka核心模块使用Scala语言开发…

MySQL基础架构

文章目录 MySQL基础架构一、连接器 - 建立连接&#xff0c;权限认证二、查缓存 - 提高效率三、分析器 - 做什么四、优化器 - 怎么做五、执行器 - 执行语句六、存储引擎1、存储引擎的概述2、存储引擎的对比3、存储引擎的命令4、存储引擎的选择 MySQL基础架构 大体来说&#xff…

力扣-20. 有效的括号(回顾知识哈希表,栈)

给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有…

HTML万字学习总结

html文本标签特殊符号图片音频与视频超链接表单列表表格语义标签(布局) html文本标签 标签简介<html></html>根目录<head></head>规定文档相关的配置信息&#xff08;元数据<body></body>元素表示文档的内容<meta></meta>表示…

“技多不压身”是什么意思?看完这篇文章你会明白:有了手艺,走遍天下都不怕!

“技多不压身”是什么意思&#xff1f;看完这篇文章你会明白&#xff1a;有了手艺&#xff0c;走遍天下都不怕&#xff01; 咱们的老祖宗流传一句话&#xff1a;“一招鲜&#xff0c;吃遍天。”这话说得直白&#xff0c;却道出了学一门手艺或技术对于人生的重要性。“李秘书讲…

Linux 学习笔记(16)

十六、 计划任务 在很多时候为了自动化管理系统&#xff0c;我们都会用到计划任务&#xff0c;比如关机&#xff0c;管理&#xff0c;备份之类的操作&#xff0c;我 们都可以使用计划任务来完成&#xff0c;这样可以是管理员的工作量大大降低&#xff0c;而且可靠度更好。 l…

电商经济和实体经济,哪个更有发展力?这篇文章讲的很详细!

我是电商珠珠 三年的冲击&#xff0c;使实体经济走向衰败&#xff0c;以至于到今天很多实体店仍无法正常营业&#xff0c;面临赔本的惨状。花大好几十万去做这件事&#xff0c;结果分币未挣。近年来&#xff0c;电商虽然发展的很快&#xff0c;但是平台众多&#xff0c;规则也…

“入站营销“VS“即时流量变现“客户该进谁家门?

在不断变化的市场环境下&#xff0c;两种主导战略“入站营销 ”和 “即时流量变现”决定了企业接触受众的方式。了解这些方法之间的根本区别对于企业制定有效的营销战略至关重要。 受众体的差别线索质量 “即时流量变现”&#xff0c;顾名思义&#xff0c;短时间&#xff0c;…

Leetcode - 周赛388

目录 一&#xff0c;3074. 重新分装苹果 二&#xff0c;3075. 幸福值最大化的选择方案 三&#xff0c;3076. 数组中的最短非公共子字符串 四&#xff0c;3077. K 个不相交子数组的最大能量值 一&#xff0c;3074. 重新分装苹果 本题是一道阅读理解题&#xff0c;就是将数组a…

springboot“力炫”健身馆网站

摘要 随着网络科技的不断发展以及人们经济水平的逐步提高&#xff0c;网络技术如今已成为人们生活中不可缺少的一部分&#xff0c;而信息管理系统是通过计算机技术&#xff0c;针对用户需求开发与设计&#xff0c;该技术尤其在各行业领域发挥了巨大的作用&#xff0c;有效地促…

7.1strcmp

strcmp 函数原型 extern int strcmp(const char *s1,const char *s2);规则 当s1<s2时&#xff0c;返回为负数&#xff1b; 当s1s2时&#xff0c;返回值0&#xff1b; 当s1>s2时&#xff0c;返回正数。 即&#xff1a;两个字符串自左向右逐个字符相比&#xff08;按ASCI…

springboot项目自定义切面增强方法功能(springboot记录日志)

说明 背景&#xff1a;记录系统接口日志入库&#xff0c;包含接口方法、入参、回参、响应时间、操作人、操作时间等信息。 方案&#xff1a;添加自定义切面处理 一、自定义切面注解 package com.gstanzer.supervise.annotation;import com.gstanzer.supervise.enums.Busine…

【BFS】走迷宫问题——acwing844

问题描述 给定一个 nm 的二维整数数组&#xff0c;用来表示一个迷宫&#xff0c;数组中只包含 0 或 1&#xff0c;其中 0表示可以走的路&#xff0c;1 表示不可通过的墙壁。 最初&#xff0c;有一个人位于左上角 (1,1) 处&#xff0c;已知该人每次可以向上、下、左、右任意一…

Ubuntu20下C/C++编程开启TCP KeepAlive

1、在linux下&#xff0c;测试tcp保活&#xff0c;可以使用tcp自带keepalive功能。 2、几个重要参数&#xff1a; tcp_keepalive_time&#xff1a;对端在指定时间内没有数据传输&#xff0c;则向对端发送一个keepalive packet&#xff0c;单位&#xff1a;秒 tcp_keep…

学习开发小程序的起航日记

2024年3月16日 不知不觉中三月份还只剩了一半的光景&#xff0c;我想写的内容还很多没有写&#xff0c;或者更应该说&#xff0c;是想积累的还有很多。现在最应该去完善Java的内容&#xff0c;可还是想先等等。想等搞清楚小程序部分&#xff0c;想等积累完小程序的内容。 这几…

unraid docker.img扩容

unraid 弹Docker image disk utilization of 99%&#xff0c;容器下载/更新失败 我的版本是6.11.5&#xff0c;docker.img满了导致容器不能更新&#xff0c;遇到同样问题的可以先用docker命令清除一下仓库(当然不一定能清理出来&#xff0c;我已经清理过只清理出来1G多点&…

黑马微服务p30踩坑

报错详情 : orderservice开不起来 : 发生报错 : 然后检查了以下端口啥的 &#xff0c;配置啥的都是没有问题的 ; 解决办法 : 1 . 修改nacos1,2,3中的端口&#xff0c;将conf 中 cluster.conf中 的 127.0.0.1 全部改成自己本机的真实ipv4地址; 本机真实ipv4地址查看 :…