Java 笔记 13:接口,java.util.Comparator,java.lang.Comparable,JDK1.8 接口新特性,内部类

接口

接口的思想,一开始不好理解。但是语法很简单。
*

  • 1、接口
  • 行为标准
  • 生活中:
  • 例如:USB接口
  • 有了标准,
  • (1)电脑设计时简单了,多提供几个USB接口,就可以让很多的设备和我电脑连接
  • (2)对于其他设备的厂商也简单了,只要你这个设备有与电脑连接的需求,那么就可以把连接口设计为USB
  • 例如:电源接口
  • 有了标准:
  • (1)插座的设计
  • (2)电器的设计
  • Java中:
  • 为了限定某些类(这些类之间可能没有继承关系,甚至都不是一个派系里面的),但是这些类都具有相同的行为特征。
  • 例如:
  • Bird类
  • Plane类
  • Kite类
  • 这些类不是同一个父类派生出来的,但是又希望它们有相同的行为特征,这个时候就可以设计接口。
  • 这个时候通过这个接口就可以同时管理这些类。
  • 例如:JDBC
  • Java中,设计了很多接口,Connection(连接数据库),Statement(执行sql语句),ResultSet(返回结果)
  • Java中无法去替数据库厂商,去编写代码,那只能设计标准。
  • 因为数据库厂商太多了,有oracle,mysql,sql server,db2…
  • 如果你的数据库厂商的数据库产品想要和我Java程序连接,那么就必须遵循我的标准。
  • 2、如何声明接口?
  • 3、使用者如何去实现接口?

一、如何声明接口?

  • 1、接口的语法格式:
  • 【权限修饰符】 interface 接口名{
  •  接口的成员列表;
    
  • }
  • 2、接口的成员
  • JDK1.8之前:只能有两种成员
  • (1)全局的静态的常量:public static final,而且这三个单词可以省略
  • 为什么只能是常量?
  • 因为标准中,只能写定死的
  • (2)公共的抽象的方法:public abstract,而且这两个单词可以省略
  • 为什么只能是抽象方法?
  • 标准中只规定有什么行为标准,行为特征。至于你怎么实现,那么你自己说了算。
  • 二、 如何实现接口?
  • 语法格式:
  • 【修饰符】 class 实现类 implements 父接口们{
  • }
  • 三、接口的特点
  • 1、接口是标准,就是用来被遵守的,即就是用来被实现的,那么要求实现类在实现接口时,必须实现/重写所有的抽象方法,
  • 否则这个实现类就得是一个抽象类。
  • 2、接口也是不能直接创建对象的
  • 3、接口类型的变量与实现类的对象构成多态引用
  • 4、一个类继承父类时,我们说Java只支持单继承,但是一个类在实现接口时,可以同时实现多个接口
  • 5、一个类如果同时继承父类,又实现接口时,要求继承在前,实现在后
  • 【修饰符】 class 实现类 extends 父类 implements 父接口们{
  • }
  • 6、在Java中,接口还可以继承接口
  • 【权限修饰符】 interface 子接口 extends 父接口们{
  • }
public class TestInterfaceDefineAndUse {
	public static void main(String[] args) {
//		Flyable f = new Flyable();//接口不能直接创建对象的
		Flyable[] sky = new Flyable[3];
		//数组的元素类型Flyable类型,是接口类型
		sky[0] = new Bird();//多态引用
		sky[1] = new Plane();
		sky[2] = new Kite();
		
		for (int i = 0; i < sky.length; i++) {
			//数组的元素类型Flyable类型,是接口类型
			sky[i].fly();
		}
	}
}
//声明一个Flyable接口
interface Flyable{
//	public static final long MAX_SPEED = 7900000;
	long MAX_SPEED = 7900000;
	
//	public abstract void fly();
	void fly();
}
//声明一个Jumpable接口
interface Jumpable{
	void jump();
}
class Animal{
	
}
//让小鸟继承Animal,并实现Flyable和Jumpable
class Bird extends Animal implements Flyable,Jumpable {

	//重写接口的抽象方法,实现接口的抽象方法
	@Override
	public void fly() {
		System.out.println("小鸟振翅高飞");
	}

	@Override
	public void jump() {
		System.out.println("双脚跳");
	}
	
}
class Plane implements Flyable{

	@Override
	public void fly() {
		System.out.println("靠发动机带动飞行");
	}
	
}
class Kite implements Flyable{

	@Override
	public void fly() {
		System.out.println("靠人放");
	}
	
}

interface A{
	void a();
}
interface B{
	void b();
}
interface C extends A,B{
	void c();
}
class Impl implements C{

	@Override
	public void a() {
	}

	@Override
	public void b() {
	}

	@Override
	public void c() {
	}
	
}

java.util.Comparator

java.util.Comparator接口:

  • 抽象方法:int compare(T o1, T o2)
  • 因为是泛型,我们还没讲。现在就把T擦除,换成Object
  • java.util.Comparator接口:
  •  抽象方法:int compare(Object o1, Object o2)
    
  • 这个接口是代表Java中比较两个对象的大小标准。而且是一种“定制”比较的标准。
  • 这个接口中没有规定如何比较两个对象的大小,
  • 但是规定了,如果你认为o1 大于 o2,就返回正整数表示
  •          如果你认为o1 小于  o2,就返回负整数表示
    
  •         如果你认为o1 等于  o2,就返回0表示
    
public class TestComparator {
	public static void main(String[] args) {
		Student s1 = new Student("杨洪强", 24, 89);
		Student s2 = new Student("苏海波", 23, 100);
		
		//比较s1和s2的大小
		/*if(s1 > s2){//错误的
			System.out.println("s1 > s2");
		}*/
		AgeComparator c = new AgeComparator();
		if(c.compare(s1, s2) > 0){//如果比较s1,s2的结果是正整数,说明s1>s2
			System.out.println("s1 > s2的年龄");
		}else if(c.compare(s1, s2) <0){
			System.out.println("s1 < s2的年龄");
		}else{
			System.out.println("s1 = s2的年龄");
		}
		
		ScoreComparator s = new ScoreComparator();
		if(s.compare(s1, s2) > 0){//如果比较s1,s2的结果是正整数,说明s1>s2
			System.out.println("s1 > s2的成绩");
		}else if(s.compare(s1, s2) <0){
			System.out.println("s1 < s2的成绩");
		}else{
			System.out.println("s1 = s2的成绩");
		}
		System.out.println("-------------------------------------");
		
		Student[] all = new Student[5];
		all[0] = s1;
		all[1] = s2;
		all[2] = new Student("张三",23,88);
		all[3] = new Student("李四",24,44);
		all[4] = new Student("王五",25,45);
		
		//Arrays工具类
//		Arrays.sort(all);
		/*
		 * public static void sort(Object[] a, Comparator c)
		 * 第一个形参:需要排序的数组,Object[]说明可以是任意类型的对象数组
		 * 第二个形参:比较器对象     Comparator接口不能创建对象,只能传入实现类对象
		 */
//		Arrays.sort(all, new AgeComparator());
		//按照成绩必须交
		Arrays.sort(all, new ScoreComparator());
		
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
	}
}
//实现Comparator接口,来定制两个学生比较的具体实现方式
//例如:按照年龄比较
class AgeComparator implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		//(1)向下转型
		Student s1 = (Student) o1;
		Student s2 = (Student) o2;
		
		//(2)开始比较
		if(s1.getAge() > s2.getAge()){
			return 1;
		}else if(s1.getAge() < s2.getAge()){
			return -1;
		}
		return 0;
	}
	
}

//实现Comparator接口,来定制两个学生比较的具体实现方式
//例如:按照成绩比较
class ScoreComparator implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		//(1)向下转型
		Student s1 = (Student) o1;
		Student s2 = (Student) o2;
		
		//(2)开始比较
		if(s1.getScore() > s2.getScore()){
			return 1;
		}else if(s1.getScore() < s2.getScore()){
			return -1;
		}
		return 0;
	}
	
}

class Student{
	private String name;
	private int age;
	private int score;
	public Student(String name, int age, int score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	public Student() {
		super();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	
}

java.lang.Comparable

java.util.Comparator:定制比较,定制顺序

  •  int compare(Object o1, Object o2):
    
  •  		o1与o2比较,o1>o2,返回正整数
    
  •  		o1与o2比较,o1<o2,返回负整数
    
  •  		o1与o2比较,o1=o2,返回0
    
  • java.lang.Comparable:自然比较,自然顺序
  •  int compareTo(Object obj)
    
  •  		this与obj对象比较,this > obj,返回正整数
    
  •  		this与obj对象比较,this < obj,返回负整数
    
  •  		this与obj对象比较,this = obj,返回0
    
  • 上午讲的定制比较器,用定制比较器的对象,比较两个学生对象:
  •  AgeComparator c = new AgeComparator();
    
  •  if(c.compare(s1, s2) > 0){...}
    
  • 希望学生对象本身就具备比较大小的能力。
public class TestComparable {
	public static void main(String[] args) {
		Student s1 = new Student("杨洪强", 24, 89);
		Student s2 = new Student("苏海波", 23, 100);
		
		//按成绩比较
		if(s1.compareTo(s2)>0){
			System.out.println("s1 > s2成绩");
		}else if(s1.compareTo(s2)<0){
			System.out.println("s1 < s2成绩");
		}else{
			System.out.println("s1 = s2成绩");
		}
		
		//按年龄比较,只能再用定制比较,补充完成这个功能
	}
}
class Student implements Comparable{
	private String name;
	private int age;
	private int score;
	public Student(String name, int age, int score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	public Student() {
		super();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	@Override
	public int compareTo(Object obj) {
		//this与obj比较,this和obj都是学生对象
		Student other = (Student) obj;
		//例如:对于学生对象来说,最常用的是按成绩排名,那么我就可以把自然顺序定位成绩升序
/*		if(this.score > other.score){
			return 1;
		}else if(this.score < other.score){
			return -1;
		}
		return 0;*/
		
		return this.score - other.score;
	}
}

总结:

  • Arrays的sort方法有两种:
  • (1)void sort(Object[] arr):
  •  根据元素的自然顺序对指定对象数组按升序进行排序。数组中的所有元素都必须实现 Comparable 接口。
    
  • (2)void sort(Object[] arr, Comparator c):
  •  根据“指定比较器”产生的顺序对指定对象数组进行排序。数组中的所有元素都必须是通过“指定比较器”可相互比较的
    
public class TestArrays {
	public static void main(String[] args) {
		Student[] all = new Student[5];
		all[0] = new Student("杨洪强", 24, 89);
		all[1] = new Student("苏海波", 23, 100);
		all[2] = new Student("张三",23,88);
		all[3] = new Student("李四",24,44);
		all[4] = new Student("王五",25,45);
		
		//如果我们的学生类Student,实现了java.lang.Comparable接口,
		//能不能按照自然排序的规则进行排序呢
		//Arrays中有这样的方法
		//public static void sort(Object[] a)
		
		Arrays.sort(all);//这里面排序过程中,调用了元素本身的compareTo()方法
		//因为元素本身是Student类型,它实现了java.lang.Comparable接口
		//本身就具备比较大小的能力,即拥有compareTo()方法
		
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
	}
}

练习
Employee.java

package com.java.test1;

public class Employee implements Comparable<Object>{
	private int num;
	private String name;
	private int age;
	private int salary;
	public Employee(int num, String name, int age, int salary) {
		super();
		this.num=num;
		this.age=age;
		this.name=name;
		this.salary=salary;
	}
	public Employee() {
		super();
	}
	public int getNum() {
		return this.num;
	}
	
	public int getSalary() {
		return this.salary;
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		Employee e = (Employee)o;
		if(this.num>e.getNum()) {
			return 1;
		}else if(this.num<e.getNum()) {
			return -1;
		}
		return 0;
	}
	@Override
	public String toString() {
		return "Employee [id=" + num + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
	}
}

SalaryComparator.java

package com.java.test1;

import java.util.Comparator;

public class SalaryComparator implements Comparator<Object> {


	@Override
	public int compare(Object o1, Object o2) {
		// TODO Auto-generated method stub
		Employee e1 = (Employee)o1;
		Employee e2 = (Employee)o2;
		if(e1.getSalary()>e2.getSalary()) {
			return 1;
		}else if(e1.getSalary()<e2.getSalary()) {
			return -1;
		}
		return 0;
	}
	
}

test.java

package com.java.test1;

import java.util.Arrays;

public class test {
	public static void main(String[] args) {
		
		Employee[] all = new Employee[3];
		all[0] = new Employee(2, "王小二", 22, 20000);
		all[1] = new Employee(3, "张三", 23, 13000);
		all[2] = new Employee(1, "李四", 24, 8000);
		
		//调用java.util.Arrays的sort方法进行排序,遍历结果
		Arrays.sort(all);
		
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
		System.out.println("-----------------------------");
		
		//再次调用java.util.Arrays的sort方法进行排序,遍历结果
		Arrays.sort(all, new SalaryComparator());
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
	}
}

Java中对象要比较大小,:(1)实现Comparable(2)实现Comparator
*

  • 我们发现:java.lang.String类型,实现了Comparable接口,
  • 说明String类型中有int compareTo(Object obj)
public class TestString {
	public static void main(String[] args) {
		String s1 = "Hello";
		String s2 = "hai";
		
/*		if(s1 > s2){//因为String类型是引用数据类型,是无法直接用>和<等比较运算符比较大小的
			//...
		}*/
		
		/*
		 * h和c比较,h>c,直接就决定了s1>s2
		 */
		if(s1.compareTo(s2)>0){
			System.out.println("s1 > s2");
		}else if(s1.compareTo(s2)<0){
			System.out.println("s1 < s2");
		}else{
			System.out.println("s1 = s2");
		}
		
		Employee[] all = new Employee[3];
		all[0] = new Employee("2", "王小二", 22, 20000);
		all[1] = new Employee("3", "张三", 23, 13000);
		all[2] = new Employee("1", "李四", 24, 8000);
		
		Arrays.sort(all);
		
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
	}
}

JDK1.8 接口新特性

1、Java8对接口进行了修改:

  • Java8之前,接口中的成员只有两种:
  • (1)全局的静态的常量:public static final,可以省略
  • (2)公共的抽象的方法:public abstract,可以省略
  • Java8之后,接口又增加了两种新成员:
  • (3)静态方法:public static,不可以省略
  •  调用方式:接口名.静态方法(实参列表)
    
  • (4)默认方法:public default,不可以省略
  • 2、为什么Java8要允许接口中定义静态方法?
  • 是因为JDK发展了一段时间后,发现类库中,多了很多这样的成组的API:
  • (1)Path接口和Paths工具类
  • (2)Collection接口和Collections工具类
  • 一般工具类中都是静态方法,这些静态方法,基本上都是为前面这个对应接口服务的。
  • 这样的话,就会出现很多API,使得程序员的学习成本增加了,使用成本也增加了。
  • 开始把这样的静态方法,直接挪到接口中定义就好了。减少了这样的工具类的出现。
  • 3、为什么么Java8要允许接口中定义默认方法?
  • 是因为有的时候,一个接口它的大多数实现类对接口的抽象方法的实现代码是一样,那么我们写好几次就太麻烦了。
  • 即相当于,默认方法是原来的抽象方法有了一个默认实现。如果实现类的实现和接口一样,就不需要重写,如果不一样就重写即可。
  • 4、冲突问题
  • (1)当一个类同时实现了两个甚至更多个接口时,这些个接口中出现了方法签名相同的默认方法时,
  • 那么我们必须在这个实现类中,做出选择。
  • 选择一:保留其中一个,放弃另一个
  • 选择二:两者都不用,完全重写一个
  • (2)当一个类同时继承了父类,又实现了接口,那么当父类中出现了和接口中方法签名一样的方法时,怎么办?
  • 那么我们怎么选择?
  • 选择一:默认选择,编译器默认选择父类
  • 选择二:改选保留接口的
  • 选择三:完全自己重写
public class TestInterface18 {
	public static void main(String[] args) {
		MyInter.test();
		
//		MyInter my = new MyInter();//接口不能创建对象
		
//		MyInter my = new InterImpl1();
//		my.method();
		
		Son s = new Son();
		s.test();
	}
}
interface MyInter{
	public static void test(){
		System.out.println("接口中的静态方法");
	}
	
	void fun();
	
	public default void method(){
		System.out.println("接口中的默认方法");
	}
}
class InterImpl1 implements MyInter{

	@Override
	public void fun() {
		System.out.println("aaaa");
	}
	
}
class InterImpl2 implements MyInter{

	@Override
	public void fun() {
		System.out.println("aaaa");
	}
	
}
class InterImpl3 implements MyInter{

	@Override
	public void fun() {
		System.out.println("bbbb");
	}

	//在类中,重写接口的默认方法是,default要去掉
	@Override
	public void method() {
		System.out.println("重写接口的默认方法");
	}
	
}
interface A{
	public default  void test(){
		System.out.println("aaa");
	}
}
interface B{
	public default  void test(){
		System.out.println("bbb");
	}
}
class C implements A,B{
	//选择一:保留其中一个,放弃另一个
	//在类中,重写接口的默认方法是,default要去掉
/*	public void test(){
//		A.super.test();//保留A接口的实现
		B.super.test();//保留B接口的实现
	}*/
	
	public void test(){
		System.out.println("ccc");
	}
}

class Father{
	public void test(){
		System.out.println("ffff");
	}
}
interface D{
	public default void test(){
		System.out.println("dddd");
	}
}
class Son extends Father implements D{
	//选择一:默认选择,保留父类的
	//选择二:该选,保留干爹的
//	public void test(){
//		D.super.test();
//	}
	
	//选择三:完全自己重写
	public void test(){
		System.out.println("ssss");
	}
}

内部类

1、内部类:

  • 定义在另外一个类里面的类,就叫做内部类,为了区别,把外面的类称为外部类。
  • 2、分类
  • 根据内部类的所在的位置不同:
  • (1)成员内部类:外部类中方法外
  • (2)局部内部类:方法体内,(虽然也可以在代码块内,但是不讨论这个)
  • 成员内部类:
  • (1)有static修饰的:静态成员内部类,我们通常就简称为静态内部类
  • (2)没有static修饰的:非静态成员内部类,我们通常就简称为成员内部类
  • 【修饰符】 class 外部类{
  •  【其他修饰符】  static class 静态内部类{
    
  •  }
    
  •  【其他修饰符】   class 非静态成员内部类{
    
  •  }
    
  • }
  • 【修饰符】 class 外部类 【extends 父类】 【implements 父接口们】{
  •  【其他修饰符】  static class 静态内部类   【extends 父类】  【implements 父接口们】{
    
  •  }
    
  •  【其他修饰符】   class 非静态成员内部类   【extends 父类】  【implements 父接口们】{
    
  •  }
    
  • }
  • 说明:外部类、内部类的父类、父接口没有关系,各是各的
  • 局部内部类:
  • (1)有名字的局部内部类:简称局部内部类
  • (2)没名字的局部内部类:简称匿名内部类
  • 局部内部类的语法格式:
  • 【修饰符】 class 外部类 【extends 父类】 【implements 父接口们】{
  •  【修饰符】 返回值类型   方法名(【形参列表】){
    
  •  		【修饰符】  class 有名字的局部内部类   【extends 父类】  【implements 父接口们】{
    
  •  			...
    
  •  		}
    
  •  }
    
  • }

匿名内部类

  • 匿名内部类的语法格式:
  • 特殊
    一、匿名内部类
  • 语法格式:
  • new 父类名(【实参列表】){
  •  类的成员列表
    
  • }
  • 说明:如果你子类调用的是父类的无参构造,那么()中实参列表不用写,如果子类调用的是父类的有参构造,那么就在()中传入实参列表
  • new 父接口名(){
  • 类的成员列表
  • }
  • 特殊:声明匿名内部类与创建它的对象是一起完成的。即匿名内部类只有唯一的对象。
public class TestAnonymousInner {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		//1、需求1:要声明一个Object的子类,匿名子类,
		//并在子类中声明一个方法public void test(){}打印“hello匿名内部类"
		
		//下面这段代码,声明了匿名内部类,也创建了它的对象
		//但是没有说这个对象干什么,编译不通过的。
/*		new Object(){
			public void test(){
				System.out.println("hello匿名内部类");
			}
		}*/
		
		//(1)我们可以把这个对象,赋值给一个变量
		//多态引用
		Object obj1 = new Object(){
			public void test(){
				System.out.println("hello匿名内部类");
			}
		};
		System.out.println(obj1.getClass());//获取对象的运行时类型
		System.out.println(obj1);//打印对象时,自动对象的toString()
		
		//这是另一个Object的匿名子类的对象
/*		Object obj2 = new Object(){
			public void test(){
				System.out.println("hello匿名内部类");
			}
		};*/
		
//		(2)我们可以用这个对象,直接调用方法
		//匿名内部类的匿名对象.方法()
		new Object(){
			public void test(){
				System.out.println("hello匿名内部类");
			}
		}.test();
		
		//java.util.Comparator接口
		//我要在这里声明一个比较器类型,用于比较两个圆的半径大小
		//把一个Comparator接口的匿名实现类对象,赋值给Comparator的变量
		//多态引用
/*		Comparator c = new Comparator(){
			@Override
			public int compare(Object o1, Object o2) {
				Circle c1 = (Circle) o1;
				Circle c2 = (Circle) o2;
				if(c1.getRadius() > c2.getRadius()){
					return 1;
				}else if(c1.getRadius() < c2.getRadius()){
					return -1;
				}
				return 0;
			}
		};
		
		System.out.println(c.compare(new Circle(1), new Circle(2)));*/
		
		Circle[] all = new Circle[3];
		all[0] = new Circle(3);
		all[1] = new Circle(2);
		all[2] = new Circle(1);
		
		//匿名内部类的匿名对象作为实参使用
		Arrays.sort(all, new Comparator(){
			@Override
			public int compare(Object o1, Object o2) {
				Circle c1 = (Circle) o1;
				Circle c2 = (Circle) o2;
				if(c1.getRadius() > c2.getRadius()){
					return 1;
				}else if(c1.getRadius() < c2.getRadius()){
					return -1;
				}
				return 0;
			}
		});
		
		
	}
}
/*class RadiusComparator implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		Circle c1 = (Circle) o1;
		Circle c2 = (Circle) o2;
		if(c1.getRadius() > c2.getRadius()){
			return 1;
		}else if(c1.getRadius() < c2.getRadius()){
			return -1;
		}
		return 0;
	}
	
}*/

class Circle{
	private double radius;

	public Circle(double radius) {
		super();
		this.radius = radius;
	}

	public double getRadius() {
		return radius;
	}

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

	@Override
	public String toString() {
		return "Circle [radius=" + radius + "]";
	}
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值