面向对象

概述:java编程语言是纯粹的面向对象思想的语言。

现在程序开发有两个主流的方法:

(1)结构化程序设计,也叫面向过程程序设计,结构化程序设计主张以功能/步骤来进行软件设计。

    如在解决问题时,主要是思考的是解决问题的步骤思路:

    围棋游戏:

    1.游戏开始,2,黑棋执行,3,绘制图片,4,判断输赢,5,白棋执行,6,绘制图片,7,判断输赢,8,返回2.  9,游戏结束

结构化程序设计是以函数为程序单元 ,从一个函数开始,调用其他普通函数,进行一些数据处理,一直调用下去。

设计思想:自顶而下,逐步精分,模块化

此种方式的编程语言有C,Basic,Pascal

(2)面向对象程序设计。

       面向对象编程思想逐渐成熟起来。

      它使用类,对象,继承,封装,消息等概念来进行程序设计。主要从现实世界的客观事物(即对象)出发来进行开发软件系统,

      尽可能的运用人的自然思维方法 ,从客观事物来思考问题,认识问题。 从这些事物的本质特点,来抽象出系统所需要的类,

      作为程序的基本单元。 
      
      围棋游戏:

               黑白棋子及其行为,棋盘, 输赢规则

类是面向对象编程的基本单元,类含有一类事物的共同特征, 类可以产生多个对象,这些对象构成了程序中所需要的数据。

类是一类事物的抽象体现,而这些事物都有一些状态数据。即Field ,如,人,有身高,体重,姓名,性别,爱好等(程序设计时

,只关心业务所需要的数据), 类除了封装了一些事物的状态数据外,还提供了操作这些状态数据的方法(Method),实现逻辑。

类用来定义一种抽象数据类型。

   Field,我们称之为成员变量,有些资料称之字段,也有些资料称之为属性,java有property关键字 是属性的。 

 

从上述内容可以总结出

            成员变量(状态数据)+方法(行为)定义=类的定义        

此类方法的编程语言:C++,java,C#, Ruby          
            
  ==================================
    完成一个“猪八戒吃西瓜”这样的逻辑
    
    面向过程: 函数吃 是核心
            吃(猪八戒,西瓜)
    面向对象: 一类事物的一个:猪八戒,吃是猪八戒的行为
                        一类事物的一个:西瓜
            猪八戒.吃(西瓜)
            
  组装电脑:  
            如果是主板,硬盘,内存条这样的大件,容易组装
      ---面向对象      
            
            如果是二极管,三极管,电路板这样的小件进行组装,
            很难 ---面向过程   
       
 面向对象要比面向过程的粒度要大,相对来说容易,简单。
 面向过程要比面向对象的性能要高,因为面向对象要进行对象的实例化,比较吃内存,吃性能。  

===========================================
抽象数据类型:用一堆不同类型的状态数据来描述的一种新的事物。
          
   reg:  描述电脑,
                         颜色,     尺寸,  型号,      主板,              内存,    硬盘,显卡                         
                      0xFF00FF  15.6  thinkpadT460  华硕               三星       希捷 , inter
                      0xFF00FF  15.6  lenovoE40       三星               三星       西数 , inter
    
    这些事物的共同行为:
                       办公
            playGame
            play
            
     用状态数据(成员变量)总结一类事物的共同特征,用方法总结一类事物的共同行为。

类的定义:   =成员变量+方法

    格式语法:
      修饰词  class  类名{
      type  field1;
      type  field2;
      .....
      
            修饰词 返回值类型  method1(形参){}
            修饰词 返回值类型  method2(形参){}
      .....     
   }
=====================================
         
   对象:类的实例化,即类中的个体        

   如何创建对象:使用关键字new

            类名   引用变量  = new 类名();
         
  引用变量,简称引用,存储的是对象的地址信息,我们可以理解为变量指向了堆中的对象 
  
  成员变量的调用:引用.成员变量名

 方法的调用:引用.方法名(有参传参)    
         
 类与对象的关系:类是对象的模板,对象是类的实例化
             
 内存管理机制:

     jvm将其管理的内存分成三大主要区域:方法区,堆,栈

     方法区:用来存储jvm加载的字节码文件的信息(类的信息)包含类的方法,方法只有一份,堆中的对象共享这份方法,在使用

                   非static修饰的方法时,需要对象来调用(即动态绑定到对象上)  

     堆: 用于存储引用类型所产生的对象,如果对象有成员变量,会给成员变量分配空间

    栈:jvm在执行程序时,在栈中,会为每一个方法分配一个空间(即栈帧),用来存储方法的局部变量。当此方法结束后,栈帧消

           失,释放内存

     
基本类型的变量与引用类型的变量:

   值传递: 
       基本数据类型的变量里存储的是基本类型的数据,
       int a = 5;
       int b = a;//将a里的5复制了一份,传递给了b
   
   址传递:
       引用类型的变量里存储的是对象的地址信息
       Car c = new Car();
       Car d = c;//将c里的地址信息复制了一份,传递给了d     
 
 null与NullPointerException
    null:是引用类型的默认值
    NullPointerException:是程序在运行时产生的一种异常
                    如何产生的??  
                    当引用变量没有指向任何对象时,调用了类型中的成员变量或者方法

reg:
             Person p = null;
             p.eat("面包");
             p.name = "张三";
空指针异常:
   java.lang.NullPointerException
   在程序运行时,可能会出现此异常,出现的原因:
   Car  c = new Car();
   System.out.println(c.color);//0
   Car c = null;
   System.out.println(c.color);//就会出现空指针异常

this关键字:(这个)

      成员变量前 系统默认提供了this. 当形式参数与成员变量名称一致时,为了区分开,需要在成员变量前添加this. this指向的是

将要创建的那个对象,即,变量.方法()时的变量。当没有歧义时,this.可以省略不写

 在构造器中:还可以使用this关键字调用本类中的其他构造方法  

      语法格式: this(有参传参)

      只能在构造器中的首行首句上使用 

方法:
   概念:类的共同行为,封装了一段逻辑代码,在封装方法时,尽可能的只完成一项功能(避免将多个功能封装到一个方法内)

定义语法: 修饰词   返回值类型   方法名(....){
       
                   }

   方法的使用:
              方法属于对象的行为,应该使用:引用.方法,这些方法动态绑定到对象上 (没有static修饰的方法必须使用引用.方法(有参传参) ) 

   方法签名:
           方法名+形参列表=方法签名
           形参列表:指的是形参的类型顺序列表
           
       如:public void  sum(int a,int b)    
               问:方法签名是:  sum + int,int   
       public int   eat(String food)
               方法签名是:eat +String  

方法的重载(overload):
           在同一个类型中,方法名相同,参数列表(类型顺序)不同     
   
           在方法调用时,编译器会检查类的信息中是否有此方法签名的方法, c.sum(3,5):此时编译器检查类中是否有c.sum(int,int)这样的方法,如果有,编译通过, 没有,编译失败,并提示错误        

构造方法(构造器):
      是特殊的方法,作用是用来给成员变量(Field,字段,属性)初始化。

      特殊在
      (1)没有返回值这个位置
      (2)方法名与类型相同

 定义语法: 修饰词  类名(...){} 
    
默认无参构造器:如果定义类时,没有添加构造方法,系统会默认提供一个公有的没有形式参数的构造方法
                
                          public Point(){}
               
               注意:如果定义期间,提供了构造器,系统不再提供无参构造器。

有参构造器:因为构造器是用来给成员变量初始化的,为了方便,所以形式参数的名称都与成员变量一致。因此,在赋值时,this.不能省略。
             
构造器的调用:
                   只能是new关键字来调用 。
            new 构造方法(有参传参)。
          
          对象的实例化:是由new完成的(对象此时就存在了,但是成员变量都是默认值)
          对象的成员变量初始化:是由new调用的构造器进行的(成员变量是第一次被赋值)             

构造器的重载:
      一个类中,可以有多个构造器。
      方法名相同,参数列表不同
 

成员变量与局部变量的区别:
    成员变量
        定义位置:在方法外,类体中
        默认值:有默认值,构造器中可以不对成员变量初始化
        内存位置:在堆中
        生命周期:从对象实例化开始出现,到对象消失    
    局部变量
        定义位置:在方法内(包含小括号内的形参)      
        默认值: 没有默认值,必须初始化再使用   
        内存位置:在栈帧中
        生命周期:从声明时开始,到方法结束后,栈帧消失时。

垃圾回收机制:(GC)
     jvm的一个独有线程(程序),用于回收没有任何引用指向的对象。
     
     System.out.println((new Person()).name);
          上述产生的对象,以后再也无法使用,如果类似的这样情况有很多,对象来不及被处理,内存剩余空间就会越来越小,有可能出现内存溢出情况。因此需要一个处理机制,即垃圾回收机制。没有被引用的对象会被视为垃圾,等待GC被回收  (因为有垃圾绘制机制,所有java程序猿无需单向内存溢出或泄露情况)

继承:

       java继承是定义一种的新的类型,从已有的类中吸收成员变量和方法,新的类型可以添加新的方法和成员变量。

      优点:这种方式可以提高代码的复用性,缩短开发周期,减少开发费用。

      现实世界中:通过分析多种类型,然后发现有一些共同特征和共同行为,再将这些种类,归纳为一种新类型
      计算机语言中:先编写父类类型,再编写子类型,然后再有对象。                                                                                           

      子类可以父类中继承一些成员变量,和方法。子类还可以添加自己的独有成员变量和方法。

      子类:也叫派生类
      父类:也叫超类,基类   

关键字extends,用于继承语法
      格式:
      public class subClass extends SuperClass{
      
      }  
 
继承中的构造器:
         子类不能继承父类的构造器,但是,子类中的构造器可以调用父类的构造器
         语法: super(有参传参);
         作用:可以更好的给继承过来的成员变量赋值
         
    PS:子类中的构造器一定会有一个(至少有一个)调用了父类的构造器
              父类中如果没有无参构造器,子类需要显式调用父类构造器
              如果父类中有无参构造器,子类中的构造器可能隐式调用了父类的无参构造器.即:隐藏了super() 

继承的传递性:
             继承特征有传递特性,B类型继承了A类型的特征,C类型继承了B类型的特征。C类型也间接继承了A类型的特征
继承的另外一特点:
            单继承: 一个子类只能继承一个父类。但是一个父类可以有多个子类  

super()与this()的区别
         相同点:都是调用构造器,而且必须放在首行首句(说明super()与this()不能同时出现在一个构造器中)。
         不同点:super()是调用父类的构造器
                     this()是调用本类中其他构造器     

方法的重写(override)(子类可以重新编写继承父类的方法)

       子类可以继承父类的方法,在继承时,我们可以在子类中编写与父类中的方法名相同,参数列表也相同的方法。这就是重写。

   (1)方法名相同,参数列表相同
   (2)返回值类型可以相同,也可以是父类方法的返回值类型的子类型
   (3)修饰词可以不变,或者可以比父类的修饰权限更大  

父类型的变量可以引用子类型的对象:

 变量能调用的方法与成员变量
    如:
      Animal   a = new GoldFish();
      Animal类型的变量a引用了子类型GoldFish的对象   
      符合人类的思维:
                    这条金鱼是动物    
 方法:                   
         编译期绑定:
                在编译过程中,变量只能调出本类型中的方法
                在编译期间,  方法静态绑定到变量(变量类型)上
         运行期绑定
                 在运行过程中,真正执行的方法的逻辑与对象的类型有关系。
                 简单说成:方法在运行期间,动态绑定到对象上。
    
成员变量:
                  变量调用出的成员变量一定是本类型中的成员变量(与编译期和运行期无关)    

 Object:是所有引用类型的顶级父类,
            系统都会默认使引用类型extends Object.
此类中提供了常用的方法:
1:toString():
           在Object中,返回的是类全名@HashCode值,即对象的内存堆中的位置信息 
      
 此方法会在输出变量时,或引用变量进行拼接时默认调用。
  
  而查看地址信息,通常没有必要,我们通常要查看的是对象的成员变量信息
 
 因此我们都需要重写toString()方法,用于查看对象的详情
  格式:
   "[成员变量1="+成员变量1+",成员变量2="+成员变量2+"]"    

2:equals(Object obj)
  Object类型中的此方法中的逻辑是比较调用者this与形参obj的地址信息是否相等。
  简单说成:比较this与obj是不是同一个对象  

  所以在定义类型时,继承过来的equals方法 我们要重写。(查看两个对象的成员变量是否相等)
  重写规则:
   (1)   查看传进来的obj是不是null
             if(obj==null){
                  return false;
             }
   (2): 查看传进来的obj是不是this.
         if(obj==this){
             return true;
         }
   (3)   查看传进来的obj是不是本类型
            if(obj.getClass()!=this.getClass()){
                return false;
            }    
            可以改成
            if(!(obj instanceof Person)){
                return false;
            }

instanceof关键字:
     作用是判断引用变量指向的对象是否属于某一类型
    语法:
     boolean f =  变量名  instanceof  类型名

访问权限控制修饰词
    private,protected,public,默认的(default) 
    
    修饰类时:
        外部类:可以使用public和默认的
        内部类:可以使用public,protected,默认的,private
        
    修饰成员变量:四个都可以进行修饰       可见性不一样

                         本类中     同包下    不同包子类中      其他    
         public         true         true             true                 true
         protected   true         true             true
         default       true         true
         private       true


    在实际开发中,成员变量要尽可能的设置成不可见,
     好处是,提高代码的安全性。即用private修饰,为了在其他类中可以对成员变量进行重新设置值或者获取值,我们可以定义相应成员变量的共有方法来进行操作。
  
  public void setName(String name){
          this.name = name;//修饰成员变量的值
  }
  public  String  getName(){
          return name;
  }   
  
   修饰方法:
         与修饰成员变量的可见性一致。
         
    方法的重写:     
         子类不能重写父类的私有方法 

修饰词final:最终的,最后的

(1)修饰类,
          不能被继承,意义在 减少随意扩展功能的可能性,减少对系统的危害   
 (2)修饰变量:只能进行初始化,不能再被赋值
               成员变量: 初始化的时机有两种
                               声明时同时初始化
                               在构造器中初始化  
               局部变量:使用前初始化即可   
(3)修饰方法
         不能被重写,意义在于: 可以避免某些子类"不经意"的重写           
 

static:英文含义:静态
    1、修饰成员变量
       (1)修饰的成员变量,不属于对象的数据结构
       (2)静态变量属于类的,通常使用类名去调用
       (3)静态变量与类的信息一起存在方法区中,只存在一份,是对象的公共资源
    2、修饰方法
       (1)通常的方法都是与具体对象有关系,即对象的方法(行为)
       (2)如果是static方法则与对象毫无关系,是类的方法,通常用类名去调用,常常与参数有关系
       (3)static方法内因为无法使用this关键字,因此不能直接访问非静态成员
       (4)static方法的作用一般都用于设计成"工具方法"和"工厂方法"              
    
                   如:   Arrays.sort(数组名);
                      Math.random();
                        Math.sqrt(参);
                        Math.abs(参);
                        Math.sin(参数);
        3、static修饰代码块
               static{
                     代码逻辑
                }
        
             静态块存储在方法区中,只加载一次,与对象无关。
             执行时机为加载类的信息期间,可以理解为在实例化之前
      
            作用:通常用于加载程序中所需要的静态资源:如:图片,音频,视频等       
-------------------------------
           非静态代码块:与静态代码块,成员变量,方法都是类的成员
     {
     } 
    
          运行时机:在实例化之前执行,每次实例化之前都会执行一次  

==============================================   

常量:
     一般都是一些特殊值。
     一般都使用成员变量,修饰词为public static final
      声明时必须初始化
       命名规则: 字母全都大写
       如:   Math.PI

==============================================

设计模式之单例模式
          需求:在程序中的任何地方,我们想要获取某一个类的唯一对象。
                  我们称之为类的单例   
                  
                  
     Singleton
     (1)提供一个私有的静态的本类型的成员变量
     (2)构造器私有化
     (3)提供公有的静态的方法获取本类中创建的实例。
     
     饿汉写法:  加载期间就实例化对象
     public class Singleton{
         private static Singleton instance = new Singleton();
         private Singleton(){}
         public static Singleton getInstance(){
             return instance;
         }
     }
     懒汉写法:  调用方法时才创建对象
     public class Singleton{
         private static Singleton instance ;
         private Singleton(){}
         public static Singleton getInstance(){
             if(instance ==null){
                 instance = new Singleton();
             }
             return instance;
         }
     }        

抽象类:
   因为继承的关系,子类的功能可以越来越具体,相对来说,父类更加一般化,通用化。因为父类封装了子类的共同行为,所以,在定义时,我们可以定义方法的逻辑。有的时候,在父类中无法完成子类的功能需求,此时,不如不写,即不写方法体,代码简单化。但是此方法必须使用abstract修饰,那么此类型也必须使用abstract修饰,即抽象类
 
1、抽象方法与抽象类
  1)用abstract修饰的方法,不需要写方法体,但是得用分号来结尾 
  2)有抽象方法的类,必须使用abstract声明(修饰)
2、抽象类不能实例化
  1)  抽象类不能创建对象,没有意义
  2)  抽象类可以提供构造器(子类可继承其构造器)
  3)  抽象类中可以没有抽象方法
  4)  abstract和final不能同时修饰一个类型
3、继承抽象类
  1)若一个类继承了抽象类,那么这个类必须重写(实现)抽象类的所有抽象方法 
  2)若一个类没有实现抽象类的所有抽象方法, 那么这个类必须使用abstract修饰
4、抽象类的意义:
   1)给不同的子类定义一个父类
   2)抽象类可以封装子类的共同特征与共同行为
   3)虽然子类方法可能有不能的实现逻辑,但是方法的定义一致。

 

接口:
        有时我们需要从多个不相关的类中设计出一个子类型,而java继承是单继承的特点,无法满足我们的需求,所以,我们可以

使用接口来达到多继承的目的。 接口实际上就是一种规范制度。   (规范与规则的理解)

接口的特点:
   (1)接口使用interface关键字,而不是class,但是我们可以理解成接口是特殊的抽象类
   (2)接口里只能有抽象方法和常量     (1.8以后支持静态和默认方法)
   (3)接口不能实例化,没有任何意义
   (4)接口不能提供构造方法
 
接口中的常量:
       默认使用修饰词为public static final                      
接口中的方法
        默认使用public abstract
   
接口的实现
   (1)子类需要实现接口中的所有抽象方法,
   (2)使用implements关键字进行实现
   (3)如果子类没有实现所有抽象方法,那么子类需要使用abstract修饰
   (4)子类可以实现多个接口,接口间使用逗号分开
  
  
接口间的继承
   (1)接口与接口之间可以使用继承。子接口继承了父接口的抽象方法
   (2)支持多继承                
   
======================================
多态:面向对象的特征之一  (重写属于多态,重载可以属于多态)

     向上造型:
             父类型的变量引用子类型的对象
    (1) 父类型的变量指向不同的子类型对象,
                调用的功能有不同的实现       
       Animal  a =  new  Dog();
                   a.noise();//叫   
               a =   new  Cat();
                a.noise();//叫   
         
    (2)不同的父类型变量指向同一个对象有不同的功能
       ZhengYangDoor  a  = new  ZhengYangDoor();
            a.theftproof();//防盗
            a.openDoor();//开门
       InterA   ia = a;
               ia.theftproof();   
               
    向下造型:
        将父类型(接口)的变量赋值给子类型或者是其他父类型(接口)的变量
        Animal a = new Dog(); 
        Dog dog   =(Dog)a;
        dog.吃骨头();
        
        Cat cat = (Cat)a;//编译通过,语法正确,运行期间,造型错误
        cat.扑捉老鼠();

两个类有共同的子类可以强转

运行期间有可能会发生类造型异常:java.lang.ClassCastException 

为了避免出现错误:我们需要使用关键字instanceof来判断对象是不是要转换成的类型
         if(a instanceOf Cat){
             Cat cat = (Cat)a;
         }

 

内部类:
    是定义在一个类的内部的新类型。即内部类,另外一个类称之为外部类。
   
  根据位置不同:
                                  成员内部类
                                  方法内部类(局部内部类)
  带static修饰词的类   静态内部类
 没有名称的类:        匿名内部类  
 
 最不常用的:方法内部类,静态内部类
     方法内部类:定义在方法中,相当于局部变量,仅限于在方法中使用,定义时不能使用修饰词,可以直接访问外部类的非静态成员变量(也可以访问静态)
     静态内部类:也是以类的成员来定义的,只不过多了一个修饰词static,可以直接访问外部类的静态成员
 
相对而言,成员内部类和匿名内部类比较常用。
      成员内部类:以类的成员来定义,可以使用任何修饰词来修饰。

成员内部类访问外部类的成员
 方法内隐藏一个指向外部类对象的引用。
 外部类名.this.        

成员内部类的使用:
    创建对象:
       要先创建一个外部类的对象outer
    然后使用外部类对象去使用new调用内部类的构造器实例化
     Inner  inner = outer.new Inner(有参传参);    
外部类访问成员内部类的成员
       在外部类添加一个内部类的成员变量进行访问  
   
匿名内部类:
    没有名字的类型,写在外部类的方法中,只用一次,不需要定义类的结构,通常都是为了实现接口,抽象类或某一现有的类的子类,子类没有名称,所以称之匿名  
想使用某个类,抽象类或接口的子类对象时,当我们只想使用一次,可以不用定义子类的结构,因此我们可以使用匿名内部类的写法,因为子类没有名称,因此写的时候可以向上造型,new 父类名称(可以有参){重写接口里的所有抽象方法或抽象类的所有抽象方法,或重写某一个实现方法};

 

面向对象的三大特征:
        继承,封装,多态(抽象也被某些人认为是面向对象的第四大特征)

 封装:
            用于: 
                (1)一段逻辑代码 被封装到方法中。
                (2)方法和成员变量定义在类体中
                (3)成员变量的私有化,也是一种封装
        
          优势: 提高代码的不可见性,增加安全性。可以通过多次调用方法来提高代码的复用性。维护性强

重写、重载属于多态。

 

类与类之间的关系
      继承关系:   extends
      实现关系:     implements
      依赖关系: 有一定的偶然性,即类B以形式参数的方式通过类A的方法, 建立起的关系
      聚合关系:  我与我的朋友     与   我一定我朋友的朋友   
                          类A中可以有类B的成员变量
                          类B中也可以有类A的成员变量 
    

       

===========================================
数组:
    基本数据类型数组,元素是基本类型的数据。
  
    引用数据类型数组,元素是对象       

     初始化的方法:
         静态初始化:
                    元素类型[] 变量名  = {}
                 动态初始化:
                     (1)规定长度的
                     
                     (2)不规定长度的
   
 引用数据类型的数组使用规定长度的方式进行初始化时,
 默认值是null;
 如:
    Cell[]  cs = new Cell[10];
    
    cs里有地址,数组对象的地址。此对象里有10个null。
     
    cs[0] = new Cell(0,3);
        第二个元素存储(0,4)的方法
    cs[1] = new Cell(0,4);
    
    
PS:引用类型的数组对象内,存储的是元素对象的地址信息    
    
===================================================


   一个源文件中,只能有一个public修饰的类,而且此类必须与文件名一致。
  其他类可以不用修饰词
  main也需要在public修饰的类中,才能生效。
】   

=========================================================

【在创建子类对象时,在内存中会不会产生父类对象??】
【答案1: 会产生,没有父类对象,哪来的子类对象】
【答案2: 不会产生,创建子类对象时,子类对象的成员变量包含两部分:
       一部分为从父类中继承过来的
               在成员变量前有默认的super.
       一部分是自己本类中的
               在成员变量前有默认的this.
               
        如果子类中独有的与继承过来的成员变量重名时,必须
        显式指定使用super.或者是this.
        如果子类中没有与继承过来的成员变量相同名时,我们可以
        隐式不写,或者使用super.与this.其中任意一个。         
        
         为了避免不必要的麻烦,子类的成员变量尽可能不要与父类的
         成员变量同名       
】   

============================================================


          【类有类名和类全名之分:
                 类名:即最短的名称
                 类全名:从包名开始写的名称
           如:  String 是类名
        java.lang.String是类全名                  
          】

============================================================

package: 包.  
        作用:用于管理源文件,区分类全名
        命名规则:域名后缀.域名.项目名.模块名
        声明位置:在源文件的首行首句。
     
        类全名:从包开始写起的名称
        
    常用的包:
    java.lang.*,因为里面的类型非常常用。因此不需要导包
    java.util.*,此包下封装了很多常用的工具类 
    java.io.*,此包下封装了io流的类型
    java.net.*,此包下封装很多关于网络的多种类型 

import: 导包关键字:
        在class之上,package之下。
        用于声明 类的 类全名,在逻辑中就可以使用短的类名。
        优点: 可以减少代码的书写。

=====================================================

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值