Java 入门5

1. 多态

1.1 什么是多态?

现实世界事物描述:一个事物体现出的的不同形态! (内存中)
          水这个事物:
                  液态,固态,气态
​
从程序中描述:这个对象在内存中的变化
           猫是猫    :Cat c  = new Cat() ;
           猫是动物  :Animal a = new Cat() ;
​

1.2 多态的前提条件

1)必须存在继承关系, 如果没有继承,谈不了多态! (继承的好处第三点)
​
2)必须存在方法重写,需要让子类完成自己的业务功能,需要将父类的某些功能进行覆盖(重写)
    举例:
        动物都需要吃
        只要见到具体动物----才知道吃什么  ,具体的动物的子类将"吃"的功能进行重写
​
3)需要存在"父类引用指向子类对象"
    格式:  Fu fu =new Zi() ;
    父类名 对象名 = new 子类名() ; "向上转型"(使用的是父类的东西)

1.3多态的中的成员访问特点

成员变量:
       编译看左,运行看左! (如果编译通过了,说明Fu中存在变量,运行看左,使用父类的东西)
​
成员方法:(非静态的)
       编译看左,运行看右(因为子类出现了父类一模一样的方法声明,覆盖了)
​
静态的成员方法:算不上方法重写.和类相关的.称为"类成员"    编译看左,运行看左!
       随着类的加载而加载,访问通过类名访问
​
构造方法:
       因为存在继承关系,存在无参构造/有参构造,都需要父类先初始化,然后才是子类,分层初始化
//举例:
//父类
class Fu{
    int num = 10 ;
    public void show(){
        System.out.println("show Fu") ;
    }
    public static void method(){
        System.out.println("method Fu...");
    }
​
    public Fu(){
        System.out.println("Fu...");
    }
}
class Zi extends  Fu{
    int num = 20 ;
    //重写了
    @Override
    public void show() {
        System.out.println("show Zi") ;
    }
​
    public static void method(){
        System.out.println("method Zi...");
    }
    public Zi(){
        System.out.println("Zi");
    }
}
public class DuoTaiDemo {
    public static void main(String[] args) {
        //需要存在"父类引用指向子类对象"
        Fu fu  = new Zi() ; //父类的引用fu---堆内存中创建的它的子类对象
        //访问成员变量
        System.out.println(fu.num) ;
        fu.show() ;
​
       // fu.method() ;
       //静态方法推荐方式:
​
      /*  Fu.method() ;
        Zi.method();*/
    }
}
​

1.4 多态的好处是什么?

1)可以提高代码的复用性(继承保证的)
​
2)可以提高代码的扩展性(由多态的保证:Fu fu = new Zi() 父类引用指向子类对象)

1.5 向上转型和向下转型

多态的在使用过程中,存在向上转型和向下转型,
向下转型使用不当,会出现问题:
​
java.lang.ClassCastException:类转换异常:
属于 "运行时期异常"----->代码不严谨导致的
//举例:
//定义动物类
class Animal{
    public void eat(){
        System.out.println("动物都需吃饭...");
    }
}
//猫
class Cat extends  Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼...");
    }
}
//狗
class Dog extends  Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头...");
    }
}
//测试类
public class DuoTaiDemo {
    public static void main(String[] args) {
        //父类引用指向子类对象:向上转型
        Animal a = new Cat() ;  //猫是动物
        a.eat() ;
​
        //还原成猫--向下转型
        Cat c = (Cat) a; //堆内存是猫: 猫是猫
        c.eat() ;
​
        //创建一只狗:父类引用指向其他子类对象
        a = new Dog() ; //狗是动物 :堆内存是狗对象
        a.eat();
        //还原成狗--向下转型
        Dog d = (Dog) a; //堆内存是还狗对象,狗是狗
        d.eat();
​
        System.out.println("--------------------------------------------") ;
        //Cat cc = (Cat) a; //符号向下转型格式(强转格式)//java.lang.ClassCastException: com.qf.duotai_03.Dog cannot be cast to com.qf.duotai_03.Cat
    }
}
​

2. 抽象类

2.1 什么是抽象类/注意事项/特点

*什么是抽象?
​
 在现实事物中,将比较概括性的事物统称为"抽象的事物"
 猫和狗是具体的动物了,他们都继承自动物类,将动物就可以看成是一个抽象的事物;
 猫和狗具体的功能应该具体体现,在动物事物中,应该给出一个声明即可,不需要具体体现!
​
*抽象类: abstract class 类名{}
 
*抽象类的注意事项:
      1)在一个类中,如果当前类中存在抽象功能(方法),那么这个类必须抽象类;
      
      2)一个抽象类中,不一定都都是抽象方法;
        
*抽象方法:没有方法体的一个成员方法,并且携带一个关键字 abstract
        权限修饰符 abstract 返回值类型 方法名(形式参数列表) ;
      
      3)抽象类的子类:
              为抽象类:一定会存在具体的子类,否则没有意义!
              为具体类:它才有意义,可以创建实例!
      4)抽象类的本质:
                  强制子类必须完成的事情!
​
*抽象类特点:不能实例化 (不能创建对象)

2.2 抽象类的成员特点:

成员变量:
    既可以是变量,也可以是常量!
​
成员方法:
    既可以是抽象方法,也可以是非抽象方法
​
构造方法:
    存在无参/有参:分层初始化
    目的:对数据进行初始化!

2.3 abstract和哪些关键字冲突?

private: 被private修饰的方法只能在本类访问;有一个abstract关键字:强制子类重写
​
final: 被final修饰的成员方法,不能被重写;而abstract强制子类重写
​
static: 被static修饰符的方法,需要被类名访问,随着类的加载而加载;而abstract需要让子类重写这个方法,通过对象名来访问(访问时机冲突)
​
方法重写的注意事项:
     子类继承父类:重写父类的方法的时候,访问权限不能更低,跟父类的权限保持一致,否则报错!
例题:一个类如果没有抽象方法,那么将这个类定义为抽象类有什么意义呢?
​
意义:就是为了不让外界new对象,不能实例化.
    抽象类特点:不能实例化 (如何实例化,通过抽象类多态实例化:具体的子类)这个类没有抽象方法,将它定义为抽象类.

3. 接口

3.1 什么是接口

1)接口实际就是描述事物本身之外的"额外功能(扩展功能)"
​
举例1:
    猫和狗事物,能够去"跳高",跳高这个动作本身并不是这些事物本身具备的功能,它们经过驯养员的特殊培训就可以具备 "跳高","做计算","钻火圈", 这个功能 "额外功能",谁能够将接口中的额外功能实现了,就具备这个功能!
​
举例2:
    电脑上的USB接口----->插上不同设备,电脑可以完成不同的动作:数据传输,打字,玩游戏,....
​
2)格式:
    关键字interface 接口名{}  ---- 接口的命名规则和类一样,"大驼峰命名法"
    
3)接口如何实现: 接口是比抽象类还抽象的一种概念!
              接口的子类------>子实现类 (接口和实现类: 实现关系  : implements)
 
4)注意事项:
 
         1)接口的子类可能是抽象类,那么肯定会存在最具体的子类,否则没有意义!
         2)具体类:就通过接口多态进行实例化!
          接口名的 对象名 = new 子实现类名() ;
  
开发中"接口和子实现类的定义名称的规则":
定义接口名之后,在定义子实现类的时候,名称都会在接口名的后面+Impl
//举例:
//设计一个台灯类(Lamp)其中台灯有灯泡类(Buble)这个属性,还有开灯(on)这个方法。
//设计一个灯泡类(Buble)(抽象类),灯泡类有发亮的方法(shine),其中有红灯泡类(RedBuble)和绿灯泡类(GreenBuble)
//他们都继承灯泡类(Buble)一个发亮的方法。 设计完成后进行测试
public abstract class Buble {
​
    //给发亮的方法声明
    public abstract void shine() ;
}
public class GreenBuble extends Buble {
    @Override
    public void shine() {
        System.out.println("灯泡可以发绿光...");
    }
}
public class RedBuble extends Buble {
    @Override
    public void shine() {
        System.out.println("灯泡可以发红光...");
    }
}
//台灯类(Lamp)
public class Lamp {
    //灯泡类(Buble
    private Buble buble ;
​
    //台灯开灯,造成灯泡发亮
    public void on(Buble buble) {//形式参数是引用类型---->抽象类:实际需要当前抽象类的子类对象:抽象类多态
            buble.shine();
    }
}
public class Test {
    public static void main(String[] args) {
​
        //抽象类多态测试
        Lamp lamp = new Lamp() ;
        Buble buble = new RedBuble() ;
        lamp.on(buble) ;
​
        buble = new GreenBuble() ;
        lamp.on(buble);
    }
}
​

3.2 接口中的成员特点:(重要)

成员变量:只能是常量:存在默认修饰符public static final 可以省略不写;
​
成员方法:只能是抽象方法:存在默认修饰符 public abstract 可以省略不写;
​
构造方法:接口没有构造方法,因为接口只是为了提供事物的额外功能,谁实现了接口,就具备这个功能!

3.3 接口和抽象类有什么区别?

1)成员区别
    接口:
        成员变量:只能是常量,存在默认修饰符 public static final  可以省略
        成员方法:只能是抽象方法,存在默认修饰符 public abstract 可以省略
        构造方法:接口没有
​
    抽象类:
         成员变量:即可以是常量,也可以是变量
         成员方法:既可以存在抽象方法,而且抽象方法abstract不能省略,也可以存在非抽象方法
         构造方法:存在:无参/有参,继承关系,先让父类初始化,然后在是子类初始化(分层初始化)
​
2)关系的区别
​
     类与类之间关系:继承关系 extends, 只支持单继承,不支持多继承,但可以多层继承
     类与接口之间的关系:实现关系 implements, 一个类继承另一个类的同时,可以实现多个接口
     接口与接口之间关系:继承关系 extends, 不仅支持单继承,也可以多继承,也可以多层继承
​
3)设计理念的区别
               抽象类----存在继承关系extends, 继承体现的是"is a"的关系
               接口----->存在实现关系implements,仅仅是将额外功能提供相关的事物,这个事物要具备额外功能
               必须实现这个接口, 体现的是一种"like a"的关系

4 形式参数问题的研究:

方法的形式参数可以是基本数据类型:实际参数需要传递当前具体的基本类型的数据值即可.      
​
方法的形式参数是引用数据类型:
      类:
        具体类: 调用该方法,实际参数需要传递的是当前具体类对象
        抽象类: 调用该方法,实际参数需要传递的是当前抽象类的子类对象,抽象类多态完成!
      接口:调用该方法,实际参数需要传递的是当前接口的子实现类对象:接口多态
//举例:
//定义一个接口
interface Love{
    void love() ;
}
//类
class LoveDemo{
    public void function(Love love){//方法的形式参数是引用类型:接口,
                                    //调用该方法,实际参数需要传的是当前接口的子实现类对象:接口多态
        love.love() ;
    }
}
//子实现类
class LoveImpl implements  Love{
​
    @Override
    public void love() {
        System.out.println("爱生活,爱Java");
    }
}
​
//测试类
public class ArgsDemo3 {
    public static void main(String[] args) {
        //需求:调用LoveDemo类中的function
        LoveDemo ld = new LoveDemo() ;
​
        //Love lo = new Love() ;//接口不能实例化
        Love lo = new LoveImpl() ; //接口多态
        ld.function(lo) ;
​
        System.out.println("------------------------") ;
​
        //匿名对象
        new LoveDemo().function(new LoveImpl());
    }
}
​

5. instanceof

instanceof:判断
格式: 对象名称 instanceOf 类名
功能: 判断当前对象名是否当前类的实例 (原码里面经常看到instanceOf)

6. 返回值问题的研究

方法的返回值类型:
     基本数据类型:简单,最终通过功能的业务操作,返回的数据结果
        举例:
           public int sum(int a,int b){}
     
     引用数据类型(重点)
        类:
          具体类:如果一个方法的返回值是一个具体类,那么该方法就需要返回当前类具体对象!
          抽象类:如果一个方法的返回值是一个抽象类型,那么该方法需要返回当前抽象类的子类对象,抽象类多态!
                                                              
        接口 :如果一个方法的返回值是接口类型,那么该方法需要返回的是当前接口的子实现类对象,接口多态!
                                                             
//举例:
interface Love{
    void love() ;
}
class LoveDemo{
    public Love function(){//方法的返回值是一个接口类型,接口不能实例化,需要返回的当前接口的子实现类对象
        //?
        //方式1:
        //接口多态
       // Love love = new LoveImpl() ;
       // return  love ;
​
        //匿名对象
        return  new LoveImpl() ;
    }
}
​
//定义子实现类
class LoveImpl implements  Love{
​
    @Override
    public void love() {
        System.out.println("love loveImpl...");
    }
}
​
//测试类
public class ReturnDemo3 {
    public static void main(String[] args) {
        //测试调用:LoveDemo中的function方法:
        LoveDemo loveDemo =new LoveDemo() ;
        Love love = loveDemo.function();
        love.love();
    }
}
​

7. 权限修饰符的范围

                  在同一个包下的当前类中    在同一个包下的子类中/无关类   在不同包下的子类中        在不同包下的无关类中
 private                Y
​
 默认修饰符               Y                      Y
​
 protected:受保护的      Y                      Y                         Y
​
 public                 Y                      Y                         Y                      Y
​
四个权限修饰符的优先级:
      从大到小---> public > protected > 默认修饰符 > private

8. 包:package

包:package---目录(文件夹)的意思
​
开发中:都使用的多级包中间.隔开
​
真实开发场景中:包的命名规则
    多级包:都是公司域名反写
    istone.net.dev.xx
    
通过包名------->区分代码的层次结构的!

8.1带包的编译和运行 (手动和自动 分别dos控制台使用)

8.1.1 在同一包下的编译和运行

首先:创建package包名(推荐多级包:中间点隔开,分包)
​
两种情况:
    1)手动方式:
        a)将你当前的多级包名创建出来
        b)先将当前的Java文件进行编译
            在当前目录中:使用javac java源文件 ---->.class文件
        c)将当前字节码文件存储在刚才1)包下
        d)带包进行运行
            java 包名.类名 
                    
​
        D:\EE_2110\day15\code\01_同一个包下的编译和运行>javac Demo.java
        D:\EE_2110\day15\code\01_同一个包下的编译和运行>java com.qf.Demo
        demo...
        D:\EE_2110\day15\code\01_同一个包下的编译和运行>   
​
    2)自动方式:
        a)对Java文件进行编译
            javac -d . 某个Java文件 ---->自动的产生包名和字节码文件
        b)带包进行运行
            java 包名.类名
                
        D:\EE_2110\day15\code\01_同一个包下的编译和运行>javac -d . Demo.java
        D:\EE_2110\day15\code\01_同一个包下的编译和运行>java com.qf.Demo
        demo...
        D:\EE_2110\day15\code\01_同一个包下的编译和运行>       

8.1.2 在不同包下的编译和运行

在不同包下的编译和运行
    直接使用自动方式
        1)将当前Demo类先进行编译
                javac -d . Demo.java
        2)将Test类进行编译
                pakcage和class中间:import 包名.类名;
                javac -d . Test.java---
                它里面用到Demo类,需要导包,而且必须保证当前类的访问权限足够大
        3)运行 com.qf.Test类
                java com.qf.Test

9. 内部类

9.1 什么是内部类?

在一个类A中定义另一个类B,那么将类B就称为类A的内部类; 类A是它的外部类!

9.2 内部类

  • 成员内部类:在一个类的成员位置定义的

  • 局部内部类:在一个类的成员方法中定义的类

1) 成员内部类 :在一个类的成员位置定义的
​
  特点:成员内部类(非静态)的成员可以访问外部类的成员,包括私有!
 
  在测试类中:
      如何直接访问成员内部类的成员---此时该成员内部类:非静态
 
  固定格式:
      外部类名.内部类名 对象名 = 外部类对象.内部类对象 ;
​
//外部类
class Outer2{
    //外部类的成员变量
    private int num = 100 ;
​
    //成员内部类
    class Inner2{
        //成员方法
        public void show(){
            System.out.println(num) ;
        }
    }
​
   //定义外部类的成员方法:访问内部类的成员
    public void method(){
        //show() ;不能这样写
        //访问Inner2成员内部类的成员:---->通过对象方法
        Inner2 inner = new Inner2() ;
        inner.show() ;
    }
}
//测试类
public class InnerClassDemo2 {
    public static void main(String[] args) {
        //创建外部类对象,访问它的method方法
      /*  Outer2 o = new Outer2() ;
        o.method() ;*/
​
      //直接访问
        // 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
        Outer2.Inner2 oi = new Outer2().new Inner2() ;
        oi.show() ;
    }
}
​
2) 成员内部类中的修饰符:
     可以private,static
 
  2.1) private: 保证数据安全性(将内部类隐藏了)
       举例:身体内有心脏;
            伪代码:
               class Body{
                   //成员内部类
                 private  class Heart{
                       //成员方法
                      //并不是所有的人都可以直接完成这个完成手术---不安全!
                      public void operator(){
                           System.out.println("心脏出问题了,需要做心脏搭桥手术...") ;
                      }
                  }
               }
 
       //测试类中直接访问Heart里面operartor
         外部类名.内部类名 对象名  = 外部类对象.内部类对象;
 
       //Body.Heart bh = new Body().new Heart() ;
       // bh .operator() ;
  
   2.2) 成员内部类里面还可能存在静态修饰符static
 
        静态的成员内部类中的成员方法(静态的还是非静态),访问外部类的成员变量,都必须是静态的
          1.静态的成员内部类随着外部类的加载而加载;
          2.如何直接访问静态的成员内部类的中成员方法
            外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
 
//定义外部类
class Outer3{
​
    public int num = 100 ;
    public static int num2 = 200 ;
    //成员内部类---加入static
    static class Inner3{//类都已经是静态的了
​
​
        //里面有一个非静态方法
        public void show(){
           // System.out.println(num) ;
            System.out.println(num2) ;
        }
        //静态方法
        public static void show2(){
            //System.out.println(num) ;
            System.out.println(num2) ;
        }
    }
​
}
//测试类
public class InnerClassDemo3 {
    public static void main(String[] args) {
​
        //外部类名.内部类名 对象名  = 外部类对象.内部类对象;
       // Outer3.Inner3 oi = new Outer3().new Inner3() ; //用不了了:只能针对非静态的成员内部类
​
        //成员内部类是静态的------将它可以看成是"外部类的静态成员"
​
//        外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
        Outer3.Inner3 oi =new Outer3.Inner3() ;
        oi.show() ;
        oi.show2() ;//静态方法
        System.out.println("--------------------------------------") ;
        //show2()的另一种方式
        //成员内部类是静态的------将它可以看成是"外部类的静态成员"而且静态的成员内部类中静态
        // 的成员方法
        Outer3.Inner3.show2() ; //静态的成员内部类的静态成员方法(推荐这种访问)
    }
}
3) 局部内部类的也是内部类的一种
 
   特点:
         局部内部类可以访问外部类的成员吗?
         可以,包括私有;
 
   面试题:
         局部内部类访问局部变量的时候,有什么要求?为什么?
         要求当前的局部变量为常量:加入final修饰 ,为什么?
             jdk8 jvm已经做了内存优化:通过反编译工具查看:num2:自动带上final修饰(默认,省略了)
             jdk7以前(包含jdk7):局部内部类访问局部变量,前面必须显示的加入final修饰
 
         局部变量的生命周期随着方法的调用而存在,随着方法调用结束而消失;
         但是局部变量还在被局部内部类的成员方法在使用,局部类的对象不会立即消失,需要等待GC回收,需要将这个变量变成
         常量,保证一直可以访问到!
              
//外部类
class Outer{
    private int num = 20 ;
  //  private int num2 = 50 ;//私有
    //成员方法
    public void method(){
        //局部变量
        final int num2 = 100 ; //jdk8 jvm已经做了内存优化:通过反编译工具查看:num2:自动带上final修饰(可以省略:优化过了)
​
        //定义局部内部类
        class Inner{
            //成员方法
            public void show(){
                //访问局部变量num3
​
                System.out.println(num) ;
                System.out.println(num2) ; //还在使用变量num2
               // System.out.println(num2) ;
            }
        }
​
        //外部类的当前这个成员方法中:创建局部内部类对象,调用show
        Inner inner = new Inner() ;
        inner.show();
    }
}
​
//测试类
public class InnerClassDemo1 {
    public static void main(String[] args) {
​
        //创建外部类对象
        Outer outer = new Outer() ;
        outer.method() ;
    }
}
​

9.3 匿名内部类

内部类的另一种格式:(重点)
匿名内部类:没有名字的类
      格式:
            new 类名/接口名(){   一般类名--->抽象类
                  重写抽象方法(){
                          业务功能;
                  }
              } ;
​
匿名内部类的本质:
              就是继承了该抽象类或者实现了该接口子类对象;
​
应用场景:
      匿名内部类的使用在方法定义中或者是方法声明上:局部位置中使用
             public void show(抽象类名 参数名){
​
               }
      1)可能方法的形式参数是一个接口/抽象类
      2)可能方法返回值类型时一个接口/抽象类
​
//定义一个接口
interface Inter{
​
    //只有一个抽象方法
    void show() ;
​
    //多个抽象方法
    void show2() ;
}
​
//定义一个外部类
class Outer{
    //有一个成员方法
    public void method(){
        //局部位置
        //方法体中:需要将Inter接口中的show进行重写
             /*class  Inner implements Inter{ //局部内部类的类名Inner
​
            @Override
            public void show() {
​
            }
        }*/
        /**
         * 匿名内部类的格式
         *  new 类名/接口名(){   一般类名--->抽象类
         *                    重写抽象方法(){
         *                           业务功能;
         *                    }
         *               } ;
         */
        /* new Inter(){
​
            @Override
            public void show() {
                System.out.println("show Inter...");
            }
​
            //重写接口中的方法
             @Override
             public void show2() {
                 System.out.println("show2 Inter...");
             }
         }.show() ;
​
        new Inter(){
​
            @Override
            public void show() {
                System.out.println("show Inter...");
            }
​
            //重写接口中的方法
            @Override
            public void show2() {
                System.out.println("show2 Inter...");
            }
        }.show2() ;*/
        //问题:当接口中的抽象方法越来越多,此时使用匿名内部类的时候,调用方法很麻烦...
        //优化:如果能够为当前匿名内部类(表示是继承了抽象类或者实现了接口的子类对象),给他起个对象名称
​
        Inter inter = new Inter() {//还是接口多态方式:不过子实现类没类名
​
            @Override
            public void show() {
                System.out.println("show Inter...");
            }
​
            @Override
            public void show2() {
                System.out.println("show2 Integer...");
            }
        };
        inter.show() ;
        inter.show2() ;
    }
}
//测试类
public class NoNameInnerClassDemo {
    public static void main(String[] args) {
​
        //创建外部类对象
        Outer outer = new Outer() ;
        outer.method() ;
    }
}
​

10. 常用类

常用类:
      JavaSE---->JavaEE:做项目中会使用大量的写Java中常使用的接口或者类
      举例:
          集合
          String
          Date日期
          StringBuffer
          线程Thread
          IO流程:InputStram/OutputStream:数据传输
          网络编程
          反射
必须知道常用类或者接口中常用的功能(方法),并且熟练使用!
 *需要使用jdk的API查询:应用程序接口文档
 *后期不断的去使用第三方的API(阿里的,腾讯,百度...)

10.1 Object类

java.lang.Object是类Object结构的根。每个类都有Object作为超类(父类)
​
常用的功能:大部分常用类已经将这些功能重写了
​
      public final Class getClass():表示正在运行的类的实例!   (当前类的字节码文件对象)(重点)
      public int hashCode():哈希码值,把它可以看成是一个"地址值",不是真实意义的地址值,和哈希表有关!(了解)
                  不同的对象,哈希码值不同
​
      Class---->后期反射中讲
          成员方法:
          public String getName():获取当前正在运行的的类名,表现字符串形式
          
 面试题:
      获取一个类的字节码文件对象的方式有几种?
         1)Object的方法 public final Class getClass()
         2)任意Java类型的class属性
​
public class ObjectDemo {
    public static void main(String[] args) {
   // Demo demo = new Demo() ;
     //   System.out.println(demo.getClass()) ;
        //创建两个学生对象
        Student s1 = new Student() ;
        Student s2 = new Student() ;
        //System.out.println(s1) ;
        //System.out.println(s2) ;
        Class c1 = s1.getClass() ;
        Class c2 = s2.getClass() ;
​
        System.out.println("----------------------------------------");
        // public String getName()
        String name1 = c1.getName();
        String name2 = c2.getName();
        System.out.println(name1+"----"+name2);
​
        System.out.println(c1) ;//包名.类名
        System.out.println(c2) ;
        System.out.println(s1==s2) ;//分别需要开辟空间
        System.out.println(c1==c2) ; //因为类就加载一次,产生的字节码文件就一个
​
        System.out.println("----------------------------------") ;
        //另一种方式也可以获取字节码文件对象
        //任意Java类型的class属性(自定义的类/jdk提供类)
        Class c3 = Student.class ;
        System.out.println(c3);
        System.out.println(c3==c2);
        System.out.println("----------------------------------------------------------------") ;
​
        int i = s1.hashCode();
        int i2 = s2.hashCode();
        System.out.println(i);
        System.out.println(i2);
​
        System.out.println("高".hashCode()) ;
        System.out.println("张".hashCode());
    }
}
​

10.1 Object的toString方法

public String toString()返回对象的字符串表示形式;应该是一个简明扼要的表达,容易让人阅读
Object 的toString 方法:获取的是某个对象的地址值,地址值没有意义
 
创建对象,输出对象名称:打印出来的对象的地址值,没有意义;
​
让所有子类覆盖toStrin此方法。打印出来应该看到的是当前这个对象的成员信息表达式!!
  
    Integer类
            int类型包装类类型
            静态功能:
            public static String toHexString(int code)
 
​
public class ObjectDemo {
​
    public static void main(String[] args) {
​
        //创建一个学生对象
        Student s = new Student("刘德华",48) ;
      //  System.out.println(s) ;//com.qf.object_01.Student@1540e19d:地址值没有意义
​
        //直接输出对象名称:等价于 访问其实就是Object类toString()方法
       // System.out.println(s.toString());//com.qf.object_01.Student@1540e19d
        /*
        *Object类的toString
        * public String toString() {
                    return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
        * */
       // String name = s.getClass().getName();
       // System.out.println(name+"@"+Integer.toHexString(s.hashCode()));//com.qf.object_01.Student
​
​
​
        System.out.println(s );
        System.out.println(s.toString()); //类似于Object obj = new Student() ;
​
​
       /* String str = new String() ;
        System.out.println(str);*/
    }
}

10.2 Object的equals方法

public boolean equals(Object obj):指示其他对象与此对象是否"相等"
​
==和equals的区别:
      ==:连接的是基本数据类型:比较的基本数据类型数据值是否相等
               int a= 10 ;
               int b = 20 ;
               a==b ;
 
      ==:连接的是引用数据类型,比较的是引用数据类型的地址值是否相同
 
      equals:默认比较的是地址值是否相同,建议子类重写equals方法,比较他们内容是否相同(成员信息是否相同)!!!
 
      在重写equals方法的同时,还需要重写hashCode()方法,保证哈希码值必须一样,才能比较equals
 
      alt+ins--->equals and hashCode
      如果重写Object类的equals方法之后,都是比较的内容是否相同(成员信息是否相同)
 
      大部分的常用类都会重写Object类的equals方法
​
public class ObjectDemo {
    public static void main(String[] args) {
​
        Student s1 = new Student("高圆圆",42) ;
        System.out.println(s1) ;
        Student s2 = new Student("高圆圆",42) ;
        System.out.println(s2);
        System.out.println(s1==s2) ;//false
​
        System.out.println("----------------------------------------") ;
​
        //public boolean equals(Object obj)
        System.out.println(s1.equals(s2)) ;//false:Student类没有重写equals
        //true:因为重写了Object的equals方法
​
        /*
         Object的equals方法的原码
            public boolean equals(Object obj) {//多态:new Student() ;
                  return (this == obj);//s1  s2 :两个对象的== :默认比较的是地址值是否相同
             }
        */
        //System.out.println("高圆圆".hashCode());
​
        /*
        
          @Override
            public boolean equals(Object o) {
                if (this == o) { //比较是地址值是否相同
                    return true;
                 }
                if (o == null || getClass() != o.getClass()) { //s2对象如果为null,或者是当前两个对象的字节码文件不相同
                    return false;
                 }
​
                Student student = (Student) o; //----Object类型:向下转型
​
                if (age != student.age){ //this.age !=student.age :和s2对象进行比较年龄是否相同
                     return false;
                 }
                return
                       name.equals(student.name); //this.name 和传进来对象的姓名比较
                       name类型:String类型:String类型底层重写Object的equals方法 :由于重写了,所以String类型里面
                       equals:比较的是字符串的内容是相同
​
            }
        */
​
    }
}

10.3 Object的clone方法

protected Object clone() throws CloneNotSupportedException:调用过程中可能存在克隆不支持的异常
 
     对于jdk提供的类的方法本身存在异常.谁调用这个方法,必须做出处理,否则报错,最简单的方式继续往上抛 throws
 
     创建并返回此对象的副本(浅克隆):了解
    
     简单理解:复制对象,获取对象的成员...
​
public class ObjectDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
​
        //之前的写法
        Student s1 = new Student("高圆圆",42) ;
​
        System.out.println(s1) ;//直接输出对象名称,等价于调用自己的toString()
        System.out.println(s1.getName()+"---"+s1.getAge()) ;
​
        //定义一个变量
        Student s2 = s1 ;
        System.out.println(s2.getName()+"---"+s2.getAge()) ;
​
        System.out.println("-----------------------------------------") ;
​
        //现在使用clone]方法:浅克隆
        Object object = s1.clone() ;//受保护的方法,无关类中不能访问...需要在当前子类中重写clone方法,需要实现Cloneable接口
​
        //上面的写法:类似于Object object = new Student() ;
        //向下转型
        Student s3 = (Student) object ;
        System.out.println(s3.getName()+"----"+s3.getAge()) ;
​
        s3.setName("赵又廷") ;
        s3.setAge(45) ;
​
        System.out.println(s1) ;
        System.out.println(s3);
​
    }
}

11. Scanner类

Scanner:java.util的类:文本扫描器
一直在用这个:录入录入数据
​
    构造方法
       public Scanner(InputStream source)
 
成员方法:
       判断功能 haxNextXXX():判断下一个录入都是是否是XXX类型
       public boolean hasNextInt():
       public boolean hasNextLine().
 
       获取功能 nextXXX()
           public int nextInt()
           public String nextLine()
           public String next()
           ...
​
public class ScannerDemo {
​
    public static void main(String[] args) {
​
        //public Scanner(InputStream source):形式参数时候一个抽象类,需要有子类对象
        //System类中存在一个"标准输入流"in
        //public static final InputStream in
        InputStream inputStream = System.in ; //字节输入流
​
        //创建键盘录入对象
        Scanner sc = new Scanner(inputStream) ;
​
        System.out.println("录入一个数据:");
​
       /* int num = sc.nextInt(); //获取功能
        System.out.println(num);*/
        //java.util.InputMismatchException:录入的数据和需要接收的num类型不匹配
        //Scanner类的提供的判断功能
        if(sc.hasNextInt()){
            //录入的int类型
            //接收int
            int num = sc.nextInt() ;
            System.out.println("您输入的数据是:"+num);
        }else if(sc.hasNextLine()){
            //录入的String
            String line = sc.nextLine() ;
            System.out.println("您输入的数据是:"+line);
        }else{
            System.out.println("对不起,没有提供其他接收的类型值...");
        }
​
    }
}
 11.1 键盘录入的细节:
       录入的字符串和,int类型
 
       先录入int,在录入字符串:字符串数据被漏掉
 
       原因:"回车符号"的问题,如何解决:
           1)可以使用next()---->录入的也是字符串
           2)在录入String之前,在创建一个新键盘录入对象:比较麻烦:比较耗内存
 
    应用场景:
           后面集合就会用到:TreeSet集合(红黑树结构): 针对元素进行排序(自然排序/比较强排序)
 
           键盘录入5个学生的语文成绩,英语成绩,数学成绩,姓名需要将5个学生的总分从高到底进行排序(TreeSet讲)
           Student
               int math;
               int english;
               int chinese;
               String name ;
 
           有String,有int数据的录入----->统一使用String接收 "98","97","89"
           String--> Integer-->int
​
public class ScannerDemo2 {
    public static void main(String[] args) {
​
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in) ;
        //提示并录入
        System.out.println("请您输入第一个数据:");
        int a = sc.nextInt() ;
​
        System.out.println("请您输入第二个数据:");
       // Scanner sc2 = new Scanner(System.in) ;
       // String b = sc2.nextLine() ;//录入的一行内容
        String b = sc.next() ;
​
        System.out.println("a:"+a+",b:"+b);
    }
}

12. String 类

12.1 String的描述

String类代表字符串.
Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。"字符串本身就是常量"
​
String的特点:
       字符串不变的; 它们的值在创建后不能被更改
​
推荐方式:
      String 变量名   =  "字符串常量" ;
​
知道:构造方法有哪些
 public String():无参构造
 String(byte[] bytes):将字节数组可以构造字符串对象
 public String(byte[] bytes,int offset,int length)一部分字节数组构造成字符串对象
 public String(char[] value):将字符数组构造成字符串对象
 public String(char[] value, int offset,int count):将一部分字符数组构造成字符串对象
 public String(String original):创建一个字符串对象,里面存储字符串常量
​
 面试题:
      数组中有没有length(),字符串String类中有没有length(),集合中有没有length()?
         没有length(),只有length属性
​
         String:有
         集合:没有----获取长度:size()
         public int length():获取字符串长度
             
         null  :空值 :没有对象 引用数据类型的默认值
         String s = null ;
         String s  = "" ; 空字符序列,有,是空的,存在对象!
                          // String s = new String("") ;
​
//举例:                          
public class StringDemo {
    public static void main(String[] args) {
        //构造方法测试
//        public String():无参构造
​
        String s1 = new String() ;
        System.out.println("s1:"+s1) ;
        System.out.println(s1.length()) ;
​
        System.out.println("---------------------------------------") ;
        //String(byte[] bytes):将字节数组可以构造字符串对象
        //创建一个字节数组
        byte[] bytes = { 97,98,99,100,101} ;
        String s2 = new String(bytes) ; //字符串底层有字符序列:字符数组----将97 寻找ASCII码表的字符内容
        System.out.println("s2:"+s2);
        System.out.println(s2.length());
        System.out.println("---------------------------------------") ;
​
//        public String(byte[] bytes,int offset,int length)一部分字节数组构造成字符串对象
        //参数1:字节数组对象,参数2:起始索引 参数3:指定长度
        String s3 = new String(bytes,1,3) ;
        System.out.println("s3:"+s3) ;
        System.out.println(s3.length());
​
        System.out.println("---------------------------------------") ;
​
        //public String(char[] value):将字符数组构造成字符串对象
        //创建一个字符串数组
        char[] chs = {'h','e','l','l','o','高','圆','圆'} ;
        String s4 = new String(chs) ;
        System.out.println("s4:"+s4) ;
        System.out.println(s4.length());
        System.out.println("---------------------------------------") ;
​
        //public String(char[] value, int offset,int count):将一部分字符数组构造成字符串对象
        String s5 = new String(chs,5,3) ;
        System.out.println("s5:"+s5) ;
        System.out.println(s5.length());
​
        System.out.println("---------------------------------------") ;
​
        //public String(String original):创建一个字符串对象,里面存储字符串常量
        String s6 = new String("hello") ;
        System.out.println("s6:"+s6);
        System.out.println(s6.length());
​
       /* String s7 = "hello" ;
        System.out.println("s7:"+s7);
        System.out.println(s7.length());*/
    }
}
​

12.2 字符串的特点

字符串的特点:
          字符串不变的; 它们的值在创建后不能被更改
 
          值:常量地址值...
 
          字符串是常量:在内存中:方法区中的常量池中存储(池化技术...)
 
 
       面试题:
           String s = "hello" ;
           和
           String s2 = new String("hello") ;两个有什么区别,分别创建了几个对象!
 
           共同点:都是在创建一个字符串对象"hello"
           但是内存执行不一样
           前者:只是在常量池中开辟空间,创建一个对象  :推荐这种方式,节省内存空间!
           后者:在堆中开辟空间,而且里面存在常量----常量池中标记 ,创建两个对象
//举例:
public class StringDemo2 {
    public static void main(String[] args) {
​
        String s1 = "hello" ; //创建一个字符串对象
​
        String s2 = new String("hello") ;
​
        System.out.println(s1 == s2) ;
        System.out.println(s1.equals(s2)) ;
        //String已经重写了Object的equals方法:默认比较就不是地址值而是内容是否相同
    }
}

12.3 String类的获取功能

String类的获取功能:
       char charAt(int index)  :获取指定索引出的字符值
       public String concat(String str):拼接功能:拼接新的字符串
       public int indexOf(int ch):返回指定字符第一次出现的字符串内的索引
       int lastIndexOf(int ch)  :查询指定字符最后一次出现的索引值
       int length()  :获取字符串长度
       public String[] split(String regex):字符串的拆分方法:返回的字符串数组 (重要)
  
       String substring(int beginIndex) :字符串截取功能   (重要)
               默认从beginIndex起始索引截取到末尾
       public String substring(int beginIndex,int endIndex)    :从指定位置开始截取到指定位置结束(包前不包后)
                   包含beginIndex位置,不包含endIndex位置,包含到endIndex-1
//举例:
public class StringDemo {
    public static void main(String[] args) {
​
        //测试
        //创建一个字符串
        String s = "helloworldJavaEE" ;
        //  char charAt(int index)  :获取指定索引出的字符值
        System.out.println("charAt():"+s.charAt(4)) ;
        System.out.println("--------------------------------------") ;
        // public String concat(String str):拼接功能:拼接新的字符串
        System.out.println("concat():"+s.concat("Android")) ;//拼接功能
        System.out.println(s+"IOS");//拼接符号
​
        System.out.println("---------------------------------------") ;
        // public int indexOf(int ch):返回指定字符第一次出现的字符串内的索引
        //参数为字符/或int: int的值也可以找ASCII码表的字符
        System.out.println("indexOf():"+s.indexOf('l'));
        //int lastIndexOf(int ch)  :查询指定字符最后一次出现的索引值
        System.out.println("lastIndexOf():"+s.lastIndexOf('l'));
​
        System.out.println("---------------------------------------") ;
​
        // public String[] split(String regex):字符串的拆分方法:返回的字符串数组 (经常用到)
        //参数可以是正则表达式或则普通字符串---分割符号
        //创建一个新的字符串对象
        String str = "Java-Php-Go-R-Python-C-C++-C#-Net" ;
​
        String[] strArray = str.split("-") ;
        for(int x = 0 ; x < strArray.length ; x++){
            System.out.print(strArray[x]+" ");
        }
        System.out.println();
        System.out.println("---------------------------------------") ;
​
​
        //截取:
        /**
         * String substring(int beginIndex) :字符串截取功能   (重要)
         *                默认从beginIndex起始索引截取到末尾
         *        public String substring(int beginIndex,int endIndex)    :从指定位置开始截取到指定位置结束(包前不包后)
         *                   包含beginIndex位置,不包含endIndex位置,包含到endIndex-1
         */
        System.out.println("subString():"+s.substring(5));
        System.out.println("subString():"+s.substring(5,10));
​
    }
}

12.4 String类的转换功能

 public char[] toCharArray():将字符串转换字符数组
          byte[] getBytes()  :使用平台的默认字符集进行编码过程:将字符串--->字节数组
          byte[] getBytes(String charset):使用指定的字符集进行编码  "GBK/UTF-8"
                      编码和解码
                              编码:将能看懂的字符串---->看不懂的字节
                              解码:将看不懂的字节----->能看懂的字符串
​
         public String toLowerCase():将字符串中的每一个字符转换成小写
         public String toUpperCase():将字符串中的每一个字符转换成大写
         
         static String valueOf(boolean b/float/long/double/int/char /....Object)
         万能方法:将任意的数据类型转换成String :静态的功能
//举例:                  
ublic class StringDemo2 {
    public static void main(String[] args) {
​
        //有一个字符串
        String s = "helloworld" ;
​
        //public char[] toCharArray():将字符串转换字符数组
        char[] chs = s.toCharArray();
        for (int i = 0; i < chs.length; i++) {
            System.out.println(chs[i]);
        }
        System.out.println("---------------------------------------------") ;
        // byte[] getBytes()  :使用平台的默认字符集进行编码过程:将字符串--->字节数组
        byte[] bytes = s.getBytes() ;
       // System.out.println(bytes);
        //看到字节数组的内容: 使用数组工具Arrays
        //static String toString(任何类型的数组)  :静态功能---将任何类型的数组转换成字符串形式
        System.out.println(Arrays.toString(bytes));
        //[104, 101, 108, 108, 111, 119, 111, 114, 108, 100] :英文:寻找它的ASCII码表
        System.out.println("---------------------------------------------") ;
​
        //public String toLowerCase():将字符串中的每一个字符转换成小写
        //public String toUpperCase():将字符串中的每一个字符转换成大写
        System.out.println(s.toLowerCase());
        System.out.println(s.toUpperCase());
        System.out.println("---------------------------------------------") ;
        /**
         * static String valueOf(boolean b/float/long/double/int/char /....Object)
         *          万能方法:
         *              将任意的数据类型转换成String :静态的功能
         */
        int i = 100 ;//int
        String result = String.valueOf(i);
        System.out.println(result) ;//数字字符串 "100"
    }
}
​

12.5 String的判断功能

String的判断功能
       public boolean contains(String s):判断是否包含子字符串
       public boolean startsWith(String prefix):判断是以指定的字符串开头
       public boolean endsWith(String suffix):判断是是以指定的字符串结尾
       boolean equals(Object anObject)  :判断字符串内容是相等:区分大小写
       boolean equalsIgnoreCase(String anotherString)  :判断字符串内容是否相等,忽略大小写
       public boolean isEmpty():判断字符串是否为空
 
public class StringDemo {
    public static void main(String[] args) {
​
        //String字符串
        String s = "helloJavaee" ;
//      public boolean contains(String s):判断是否包含子字符串
        System.out.println("contains():"+s.contains("hel"));
        System.out.println("contains():"+s.contains("ak47"));
        //  public boolean startsWith(String prefix):判断是以指定的字符串开头
        //  public boolean endsWith(String suffix):判断是是以指定的字符串结尾
        System.out.println("-----------------------------------------------") ;
        System.out.println(s.startsWith("hel"));
        System.out.println(s.startsWith("高圆圆"));
        System.out.println(s.endsWith("ee"));
        System.out.println(s.endsWith("wor"));
        System.out.println("-----------------------------------------------") ;
​
        String s2 = "helloJavaEE" ;
        System.out.println(s.equals(s2)) ; //区分大小写
        //boolean equalsIgnoreCase(String anotherString)
        System.out.println(s.equalsIgnoreCase(s2));//不区分大小写
        s = "" ;
        System.out.println(s.isEmpty());
​
    }
}

12.6 String类的其他功能

String类的其他功能
  public String replace(char oldChar,char newChar):将新的字符值把旧的字符替换掉
  public String replace(String oldChar,String newChar):将新的字符串值把旧的字符串替换掉
  public String replaceAll(String regex,String replacement):使用指定的replacement替换的字符串内容
       将符号正则表达式的匹配的字符串替换掉 (用到正则表达式使用)
       参数1:正则表达式 举例: [0-9]
 
   public String trim():去除字符串前后两端空格
               一般用在:IO中传输文件(读写文件)
 //举例:
public class StringDemo {
    public static void main(String[] args) {
​
        //public String replace(char oldChar,char newChar):将新的字符值把旧的字符串替换掉,返回的新的自测
        String s = "helloworld" ;
​
        System.out.println("replace():"+s.replace('l','k')) ;
        System.out.println("replace():"+s.replace("world","高圆圆"));
​
        System.out.println("--------------------------------------------------") ;
        //public String trim():去除字符串前后两端空格 (IO流中,上传文件:保证读取文件内容,先去除两端空格)
        String s2 = " javaEE    " ;
        System.out.println("s2:"+"-----"+s2+"-----");
        System.out.println("-------------------------------------") ;
        System.out.println("s2:"+"-----"+s2.trim()+"-----");
    }
}
面试题: 考源码
  public int compareTo(String anotherString)    :如何进行字典比较
  String s1 = "hel" ;
  String s2 = "hello" ;
 结果是多少,为什么这个值?
​
public class StringDemo2 {
    public static void main(String[] args) {
        String s1 = "hel" ;
        String s2 = "abc" ;
        String s3 = "hello" ;
​
        //public int compareTo(String anotherString)    :如何进行字典比较
        //英文字符:字典顺序比较:abcdefgh....
        System.out.println(s1.compareTo(s2)) ;
        System.out.println(s1.compareTo(s3)) ;
    }
}
​
  • String,作为形式参数传递,有什么特点?

    String类型作为形式参数和基本类型作为形式的效果一样,

    形式参数的改变不会直接影响实际参数,String类型特殊的引用类型!

    其他引用数据类型,形式参数的改变会直接影响实际参数!

13. StringBuffer

StringBuffer: 简称"字符串缓冲",线程安全的,而且可变的字符序列!
 
线程: -----多线程:Thread
       单线程 :程序的执行路径只有一条 ,不考虑安全性,只考虑效率!
       多线程 :程序的执行路径有多条,考虑安全性,效率问题不是重点!
 
面试题:StringBuffer和StringBuilder有什么区别?
       共同点:两者都是字符串区,支持可变的字符序列,而且都有互相兼容的API(功能相同的)
       不同点:
            前者:线程安全的类,多线程环境下使用居多-----同步(安全)----->执行效率低
                       银行的网站/医疗网站
            后者:线程不安全的类,单线程程序中使用居多---->不同步(不安全)----->执行效率高\
                       论坛的网站...
 
  StringBuffer的构造方法
           StringBuffer();无参构造方法  :使用居多
           StringBuffer(int capacity):指定容量大小的字符串缓冲区
           StringBuffer(String str) :指定缓冲区的具体内容str,容量大小=16个默认容量+当前字符串长度
 
           public int length()获取字符缓冲区中的长度
           public int capacity():获取字符串缓冲区中的容量大小
​
public class StringBufferDemo{
​
    public static void main(String[] args) {
        // StringBuffer();无参构造方法
        //创建一个字符串缓冲区对象
        StringBuffer sb = new StringBuffer() ; //默认的初始化容量16个(足够用了)
        System.out.println("sb:"+sb) ;
        System.out.println(sb.length()) ;
        System.out.println(sb.capacity()) ;
        System.out.println("-------------------------") ;
​
        //  StringBuffer(int capacity):指定容量大小的字符串缓冲区
        StringBuffer sb2 = new StringBuffer(50) ;
        System.out.println("sb2:"+sb2);
        System.out.println(sb2.length());
        System.out.println(sb2.capacity());
​
        System.out.println("-------------------------") ;
​
       // StringBuffer(String str) :
        String s = "helloworld" ;
        StringBuffer sb3 = new StringBuffer(s) ;
        System.out.println("sb3:"+sb3);
        System.out.println(sb3.length() );
        System.out.println(sb3.capacity() );
​
       //StringBuffer sb4 = "hello" ; //不能这样写
       /* String str = "hello" ;
        StringBuffer sb4 = str ;*/
    }
}

13.1 StringBuffer:添加字符序列/删除

StringBuffer:
           添加字符序列
              StringBuffer append(任何数据类型):将任何数据类型的数据追加字符序列中(字符串缓冲区)
              StringBuffer insert(int offset, String str)  :插入元素:在指定位置插入指定的元素
 
           删除:
               public StringBuffer deleteCharAt(int index):在指定的位置处删除的指定的字符,返回字符串缓冲区本身
               public StringBuffer delete(int start,int end):删除指定的字符从指定位置开始,到end-1处结束
//举例:
public class StringBufferDemo2 {
    public static void main(String[] args) {
        //创建一个字符串缓冲区对象
        StringBuffer sb = new StringBuffer() ;
        System.out.println("sb:"+sb);
        // StringBuffer append(任何数据类型):将任何数据类型的数据追加字符序列中(字符串缓冲区)
     /*   StringBuffer sb2 = sb.append("hello");
        StringBuffer sb3 = sb2.append('A');
        StringBuffer sb4 = sb3.append(12.56);
        StringBuffer result = sb4.append(100);
        System.out.println(result);*/
        sb.append("hello");
        sb.append("world") ;
        sb.append("javaee") ;
       /* sb.append('A');
        sb.append(true) ;
        sb.append(13.45) ;
        sb.append(100) ;
        sb.append(new Object()) ;
        System.out.println("sb:"+sb);*/
        System.out.println("sb:"+sb) ;
        // StringBuffer insert(int offset, String str)
        sb.insert(5,"高圆圆") ;
        System.out.println("sb:"+sb);
​
        //hello高圆圆worldjavaee
        System.out.println("----------------------------------------------------------") ;
//        public StringBuffer deleteCharAt(int index)
​
        //需求:删除第一个e字符
        System.out.println(sb.deleteCharAt(1));
        //需求:删除第一个l字符
        System.out.println(sb.deleteCharAt(1));
        //public StringBuffer delete(int start,int end)
        System.out.println(sb.delete(3,7));
​
    }
}

13.2 StringBuffer反转功能

public StringBuffer reverse():反转功能
//举例:
public class StringBufferDemo3 {
    public static void main(String[] args) {
        //已知一个字符串:
     /*   String s = "helloworld" ;
        //s---->StringBuffer类型
        StringBuffer sb = new StringBuffer(s) ;
​
        //利用功能
        StringBuffer sb2 = sb.reverse();
        String result = sb2.toString();
        System.out.println(result);*/
​
     //键盘录入一个字符串:将字符串反转
        Scanner sc = new Scanner(System.in) ;
​
        //提示并录入数据
        System.out.println("请您输入一个字符串:") ;
        String line = sc.nextLine() ;
​
        //调用功能改进---->String
        String result = reverse(line);
        System.out.println(result);
    }
    public static String reverse(String s){
        //s---->StringBuffer
        //分步实现
//        StringBuffer sb = new StringBuffer(s) ;
//        //反转---并且转换String
//        String result = sb.reverse().toString();
//        return  result ;
        //一步走
        return  new StringBuffer(s).reverse().toString() ;
    }
​
}
String substring(int start):从指定位置截取到默认结束,返回的新的字符串
String substring(int start, int end) :从指定位置开始截取,到指定位置结束(包前不包后)
//举例:
public class StringDemo4 {
    public static void main(String[] args) {
​
        StringBuffer sb = new StringBuffer() ;
        sb.append("helllo") ;
        sb.append("world") ;
        System.out.println(sb) ;
​
        //截取
        String resultStr = sb.substring(5);
        System.out.println(resultStr) ; //返回的被截取的字符串内容
​
        System.out.println("-------------------------------------") ;
        String resultStr2 = sb.substring(5, 9);
        System.out.println(resultStr2);
    }
}

13.3 StringBuffer <-----> String 互相转换

开发中:引用类型
      有可能将A类型转换成B类型,结果最终需要的是B类型
​
      有的时候,A类型---->B类型----->A类型
              可能需要用B类型的功能,但是结果需要的是A类型,又需要转回去
​
             StringBuffer <-----> String
//举例:
 public class StringBufferTest {
    public static void main(String[] args) {
​
        //String------->StringBuffer
        //方式1:使用StringBuffer的有参构造方法
        //StringBuffer(String s)
        String s = "helloJavaEE" ;
        StringBuffer sb = new StringBuffer(s) ;
        System.out.println("sb:"+sb) ;//内容一样,但是数据类型不同
        System.out.println("------------------------------") ;
​
        //方式2:使用StringBuffer无参构造方法+append(String s)
        StringBuffer sb2 = new StringBuffer() ;
        sb2.append(s) ;
        System.out.println("sb2:"+sb2) ;
​
​
        System.out.println("------------------------------------------") ;
        //StringBuffer-------->String
        //有一个StringBuffer的数据
        StringBuffer buffer = new StringBuffer("android") ;
        //String类型构造方法:public String(StringBuffer buffer)
        String str = new String(buffer) ;
        System.out.println("str:"+str) ;
​
        System.out.println("------------------------------------------") ;
        //public String toString()
        String str2 = buffer.toString();
        System.out.println("str2:"+str2);
​
    }
}

13.4 String和StringBuffer有什么区别?

前者: String是常量,一旦被赋值,其值不能被更改;它的不可变的字符序列
       开发中:前端提交后台的数据--------> String (它的功能远远大于StringBuffer)
       作为形式参数,形式参数的改变不会影响实际参数,特殊的引用类型,和基本数据类型作为形式参数的效果一样
​
 后者: StringBuffer是可变的字符序列,线程安全的类,同步,执行效率低,单线程程序中的使用StringBuilder替代StringBuffer
      字符串缓冲区 里面存储的字符序列-------> 还需要转换成String类型
      作为形式参数,形式参数的改变会直接影响实际参数!
​
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值