面向对象(下)

目录

  • 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.mfbz.cn/a/460723.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用reprepro+nginx搭建apt服务器

目录 项目背景 项目要求 项目开发过程 1、apt服务器的搭建 2、实现自定义指定源文件列表来实现apt update更新 3、实现软件启动时自动更新 4. source.list中镜像源地址的格式 项目开发的难点/坑点 总结 项目背景 前面写过一篇“利用Nginx搭建一个apt服务器”&#xff…

异次元发卡源码系统/荔枝发卡V3.0二次元风格发卡网全开源源码

– 支付系统&#xff0c;已经接入易支付及Z支付免签接口。 – 云更新&#xff0c;如果系统升级新版本&#xff0c;你无需进行繁琐操作&#xff0c;只需要在你的店铺后台就可以无缝完成升级。 – 商品销售&#xff0c;支持商品配图、会员价、游客价、邮件通知、卡密预选&#…

双线性插值缩放算法原理以及matlab与verilog的实现(二)

系列文章目录 双线性插值缩放算法原理以及matlab与verilog的实现&#xff08;一&#xff09; 文章目录 系列文章目录前言一、前提回顾二、FPGA实现步骤2.1 找到源图像四个像素点求目标像素点2.2 FPGA实现步骤2.3 总体框架2.4 ROM缓存模块2.5 VGA模块2.6 双线性算法模块 三、下…

【AI+应用】一步步搭建聊天机器人搭配多种国内外大模型以及api接口调用

如果你看过我之前写的一篇文章 【AI应用】怎么快速制作一个类chatGPT套壳网站&#xff0c; 你可能顺利地使用chatGPT、Gemini&#xff0c; 用得很happy。 突然有一天&#xff0c;你发现一些网站&#xff0c;除了chatGPT、Gemini &#xff0c;还可以切换使用国内外其他的大模型…

【原创】一文读懂RAG的来源、发展和前沿

检索增强生成(Retrieval Augmented Generation&#xff0c;RAG)结合了检索 (Retrieval) 和生成 (Generation) 两个过程&#xff0c;旨在提高机器生成文本的相关性、准确性和多样性。RAG通过在生成文本输出之前先检索大量相关信息&#xff0c;然后将这些检索到的信息作为上下文输…

练习题手撕总结

基础篇 1.基础知识&#xff08;时间复杂度、空间复杂度等&#xff09; 2.线性表&#xff08;顺序表、单链表&#xff09; 3.双链表、循环链表 4.队列 5.栈 6.递归算法 7.树、二叉树&#xff08;递归、非递归遍历&#xff09; 8.二叉搜索树&#xff08;BST&#xff09; 9.二分查…

FPGA静态时序分析与约束(三)、读懂vivado时序报告

系列文章目录 FPGA静态时序分析与约束&#xff08;一&#xff09;、理解亚稳态 FPGA静态时序分析与约束&#xff08;二&#xff09;、时序分析 文章目录 系列文章目录前言一、时序分析回顾二、打开vivado任意工程2.1 工程布局路由成功后&#xff0c;点击vivado左侧**IMPLEMENT…

浅易理解:非极大抑制NMS

什么是非极大抑制NMS 非极大值抑制&#xff08;Non-Maximum Suppression&#xff0c;简称NMS&#xff09;是一种在计算机视觉和图像处理领域中广泛使用的后处理技术&#xff0c;特别是在目标检测任务中。它的主要目的是解决目标检测过程中出现的重复检测问题&#xff0c;即对于…

家具工厂5G智能制造数字孪生可视化平台,推进家具行业数字化转型

家具制造5G智能制造工厂数字孪生可视化平台&#xff0c;推进家具行业数字化转型。随着科技的飞速发展&#xff0c;家具制造业正迎来一场前所未有的数字化转型。在这场家具制造业转型中&#xff0c;5G智能制造工厂数字孪生可视化平台发挥着至关重要的作用。 5G智能制造工厂数字孪…

深度学习模型部署(十)模型部署配套工具二

上篇blog讲了trtexec和onnx_graphsurgeon两个工具&#xff0c;一个用于将onnx转化为trt模型&#xff0c;另一个用于对onnx模型进行修改。这篇blog讲polygraphy和nsight systems&#xff0c;前者用于进行模型优化以及结果验证&#xff0c;后者用于性能分析。 polygraph polygra…

sqllab第二十三关通关笔记

知识点&#xff1a; mysqli_query() 返回值为资源型或布尔型如果内容为查询语句则返回资源型数据&#xff1b;如果内容为插入、更新、删除等语句则返回布尔类型结果mysql_fetch_array() 从结果集中取出一行作为关联数组或数字数组输入内容为指定查询的结果集单引号闭合绕过联…

hololens2发布unity设置

生成vs工程再向hololens发布时&#xff0c; Architecture选X64或ARM64都可以成功发布

爬虫3_爬取翻页URL不变的网站

之前实现了对大学排数据爬取&#xff1a;爬虫2_2019年549所中国大学排名. 近期复现代码&#xff0c;发现原网站升级&#xff0c;在翻页时&#xff0c;发现URL不改变&#xff0c;修改代码&#xff0c;使用网页自动化工具selenium实现对该类网站数据获取。 #-*- coding: UTF-8 -…

【物联网】Modbus 协议及Qinghub物联网平台应用

Modbus 协议简介 QingHub设计器在设计物联网数据采集时不可避免的需要针对Modbus协议的设备做相关数据采集&#xff0c;这里就我们的实际项目经验分享Modbus协议 你可以通过QingHub作业直接体验试用&#xff0c;也可以根据手册开发相应的代码块。 qinghub项目已经全面开源。 …

MC78L05ACDR2G线性稳压器芯片中文资料规格书PDF数据手册引脚图参数图片价格

产品概述&#xff1a; MC78L00A系列线性稳压器价格便宜&#xff0c;易于使用&#xff0c;适用于各种需要最高100mA的调节电源的应用。与大功率MC7800和MC78M00系列一样&#xff0c;这款稳压器也提供内部电流限制和高温关断&#xff0c;因此非常坚固耐用。在很多应用中&#xf…

MediaBox音视频终端SDK已适配鸿蒙星河版(HarmonyOS NEXT)

2024年1月&#xff0c;HarmonyOS NEXT 鸿蒙星河版系统开发者预览版开放申请&#xff0c;该系统将只能安装为鸿蒙开发的原生应用&#xff0c;而不再兼容安卓应用。对此&#xff0c;阿里云MediaBox音视频终端SDK产品已实现功能的鸿蒙化迁移和重构&#xff0c;全面适配鸿蒙系统Har…

王勇:硬科技的下一站 | 演讲嘉宾公布

一、智能耳机与可穿戴专题论坛 智能耳机与可穿戴专题论坛将于3月27日同期举办&#xff01; 智能耳机、可穿戴设备已经逐渐融入我们的生活&#xff0c;它们不仅带来了便捷与舒适&#xff0c;更在悄然改变着我们的生活方式和工作模式。在这里&#xff0c;我们将分享最新的研究成果…

前端基础——HTML傻瓜式入门(2)

该文章Github地址&#xff1a;https://github.com/AntonyCheng/html-notes 在此介绍一下作者开源的SpringBoot项目初始化模板&#xff08;Github仓库地址&#xff1a;https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址&#xff1a;https://blog.c…

误分区酿苦果,数据恢复有妙方

一、误操作引发分区混乱 在数字化时代的浪潮中&#xff0c;硬盘分区成为我们管理和存储数据的重要手段。然而&#xff0c;误分区这一操作失误&#xff0c;却时常给许多用户带来不小的困扰。误分区&#xff0c;简单来说&#xff0c;就是在对硬盘进行分区操作时&#xff0c;由于…

P6安装:安装P6提示1433端口无效

错误描述 尝试运行 Microsoft SQL Server 2005 的 Primavera P6 数据库时&#xff0c;遇到以下错误&#xff1a; SQLServerException: The TCP/IP connection to the host [name], port 1433 has failed. Error: “Connection refused: connect. Verify the connection prope…