Java 基础知识总结 (二)

141 阅读27分钟

1.异常

  异常:就是不正常。程序在运行时出现的不正常情况。其实就是程序中出现的问题。这个问题按照面向对象思想进行描述,并封装成了对象。因为问题的产生有产生的原因、有问题的名称、有问题的描述等多个属性信息存在。当出现多属性信息最方便的方式就是将这些信息进行封装。异常就是java按照面向对象的思想将问题进行对象封装。这样就方便于操作问题以及处理问题。

  出现的问题有很多种,比如角标越界,空指针等都是。就对这些问题进行分类。而且这些问题都有共性内容比如:每一个问题都有名称,同时还有问题描述的信息,问题出现的位置,所以可以不断的向上抽取。形成了异常体系。

  java.lang.Throwable:   Throwable:可抛出的。

  • Error:错误,一般情况下,不编写针对性的代码进行处理,通常是jvm发生的,需要对程序进行修正。
  • Exception:异常,可以有针对性的处理方式

  无论是错误还是异常,它们都有具体的子类体现每一个问题,它们的子类都有一个共性,就是都以父类名才作为子类的后缀名。

  这个体系中的所有类和对象都具备一个独有的特点;就是可抛性。

  可抛性的体现:就是这个体系中的类和对象都可以被throws和throw两个关键字所操作。

    class  ExceptionDemo{

    public static void main(String[] args) {

      // byte[] buf = new byte[1024*1024*700];//java.lang.OutOfMemoryError内存溢出错误

    }

  }

  在开发时,如果定义功能时,发现该功能会出现一些问题,应该将问题在定义功能时标示出来,这样调用者就可以在使用这个功能的时候,预先给出处理方式。

  如何标示呢?通过throws关键字完成,格式:throws 异常类名,异常类名...

  这样标示后,调用者,在使用该功能时,就必须要处理,否则编译失败。

  处理方式有两种:1、捕捉;2、抛出。

  对于捕捉:java有针对性的语句块进行处理。

  try {
    需要被检测的代码;
  }
  catch(异常类 变量名){
    异常处理代码;
  }
  fianlly{
    一定会执行的代码;
  }

—————————————————————————————————————————————

  catch (Exception e) { //e用于接收try检测到的异常对象。

        System.out.println("message:"+e.getMessage());//获取的是异常的信息。

        System.out.println("toString:"+e.toString());//获取的是异常的名字+异常的信息。

        e.printStackTrace();//打印异常在堆栈中信息;异常名称+异常信息+异常的位置。

  }

  异常处理原则:功能抛出几个异常,功能调用如果进行try处理,需要与之对应的catch处理代码块,这样的处理有针对性,抛几个就处理几个。

  特殊情况:try对应多个catch时,如果有父类的catch语句块,一定要放在下面。

  throw 和throws关键字的区别:

  • throw用于抛出异常对象,后面跟的是异常对象;throw用在函数内。

  • throws用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。throws用在函数上。

  通常情况:函数内容如果有throw,抛出异常对象,并没有进行处理,那么函数上一定要声明,否则编译失败。但是也有特殊情况。

  异常分两种:

  • 1:编译时被检查的异常,只要是Exception及其子类都是编译时被检测的异常。

  • 2:运行时异常,其中Exception有一个特殊的子类RuntimeException,以及RuntimeException的子类是运行异常,也就说这个异常是编译时不被检查的异常。

  编译时被检查的异常和运行时异常的区别:

  • 编译被检查的异常在函数内被抛出,函数必须要声明,否编译失败。 声明的原因:是需要调用者对该异常进行处理。

  • 运行时异常如果在函数内被抛出,在函数上不需要声明。 不声明的原因:不需要调用者处理,运行时异常发生,已经无法再让程序继续运行,所以,不让调用处理的,直接让程序停止,由调用者对代码进行修正。

  定义异常处理时,什么时候定义try,什么时候定义throws呢?

  • 功能内部如果出现异常,如果内部可以处理,就用try;
  • 如果功能内部处理不了,就必须声明出来,让调用者处理。

  自定义异常:当开发时,项目中出现了java中没有定义过的问题时,这时就需要我们按照java异常建立思想,将项目的中的特有问题也进行对象的封装。这个异常,称为自定义异常。

  对于除法运算,0作为除数是不可以的。java中对这种问题用ArithmeticException类进行描述。对于这个功能,在我们项目中,除数除了不可以为0外,还不可以为负数。可是负数的部分java并没有针对描述。所以我们就需要自定义这个异常。

  自定义异常的步骤:

    1:定义一个子类继承Exception或RuntimeException,让该类具备可抛性。

    2:通过throw 或者throws进行操作。

  异常的转换思想:当出现的异常是调用者处理不了的,就需要将此异常转换为一个调用者可以处理的异常抛出

  try catch finally的几种结合方式:

    1,
    try 
    catc
    finally

  2,
    try
    catch
    
  3,
    try
    finally

  第三种情况,如果出现异常,并不处理,但是资源一定关闭,所以try finally集合只为关闭资源。

  记住:finally很有用,主要用户关闭资源。无论是否发生异常,资源都必须进行关闭。

  System.exit(0); //退出jvm,只有这种情况finally不执行。

  当异常出现后,在子父类进行覆盖时,有了一些新的特点:

    1:当子类覆盖父类的方法时,如果父类的方法抛出了异常,那么子类的方法要么不抛出异常要么抛出父类异常或者该异常的子类,不能抛出其他异常。

    2:如果父类抛出了多个异常,那么子类在覆盖时只能抛出父类的异常的子集。

  注意:

    如果父类或者接口中的方法没有抛出过异常,那么子类是不可以抛出异常的,如果子类的覆盖的方法中出现了异常,只能try不能throws。

    如果这个异常子类无法处理,已经影响了子类方法的具体运算,这时可以在子类方法中,通过throw抛出RuntimeException异常或者其子类,这样,子类的方法上是不需要throws声明的。

  常见异常:

    1、脚标越界异常(IndexOutOfBoundsException)包括数组、字符串;

      空指针异常(NullPointerException)

    2、类型转换异常:ClassCastException

    3、没有这个元素异常:NullPointerException

    4、不支持操作异常;

  异常要尽量避免,如果避免不了,需要预先给出处理方式。比如家庭备药,比如灭火器。

2.包

:定义包用package关键字。

  1:对类文件进行分类管理。

  2:给类文件提供多层名称空间。

如果生成的包不在当前目录下,需要最好执行classpath,将包所在父目录定义到classpath变量中即可。

  一般在定义包名时,因为包的出现是为了区分重名的类。所以包名要尽量唯一。怎么保证唯一性呢?可以使用url域名来进行包名称的定义。

  package pack;//定义了一个包,名称为pack。 注意:包名的写法规范:所有字母都小写。

  //package cn.itcast.pack.demo;

  类的全名称是 包名.类名

编译命令:javac –d 位置(.当前路径) java源文件 (就可以自动生成包)

  包是一种封装形式,用于封装类,想要被包以外的程序访问,该类必须public;类中的成员,如果被包以外访问,也必须public;

  包与包之间访问可以使用的权限有两种:

    1:public

    2:protected:只能是不同包中的子类可以使用的权限。

  总结java中的四种权限:

  范围        public   protected   default   private 

  同一个类中      ok     ok       ok      ok
    
  同一包中     ok     ok       ok

  子类       ok  

  不同包中        ok

Import 导入:类名称变长,写起来很麻烦。为了简化,使用了一个关键字:import,可以使用这个关键字导入指定包中的类。记住:实际开发时,到的哪个类就导入哪个类,不建议使用*.

  import packa.*;//这个仅仅是导入了packa当前目录下的所有的类。不包含子包。

  import packa.abc.*;//导入了packa包中的子包abc下的当前的所有类。

  如果导入的两个包中存在着相同名称的类。这时如果用到该类,必须在代码中指定包名

  常见的软件包:

    java.lang : language java的核心包,Object System String Throwable jdk1.2版本后,该包中的类自动被导入。

    java.awt : 定义的都是用于java图形界面开发的对象。

    javax.swing: 提供所有的windows桌面应用程序包括的控件,比如:Frame , Dialog, Table, List 等等,就是java的图形界面库。

    java.net : 用于java网络编程方面的对象都在该包中。

    java.io : input output 用于操作设备上数据的对象都在该包中。比如:读取硬盘数据,往硬盘写入数据。

    java.util : java的工具包,时间对象,集合框架。

    java.applet: application+let 客户端java小程序。server+let ——> servlet 服务端java小程序。

    jar :java的压缩包,主要用于存储类文件,或者配置文件等。

      命令格式:jar –cf 包名.jar 包目录

      解压缩:jar –xvf 包名.jar

      将jar包目录列表重定向到一个文件中:jar –tf 包名.jar >c:\1.txt

3.线程:

3.1 线程:

  进程:正在进行中的程序。其实进程就是一个应用程序运行时的内存分配空间。

  线程:其实就是进程中一个程序执行控制单元,一条执行路径。进程负责的是应用程序的空间的标示。线程负责的是应用程序的执行顺序。

  一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序,每个线程在栈区中都有自己的执行空间,自己的方法区、自己的变量。

  jvm在启动的时,首先有一个主线程,负责程序的执行,调用的是main函数。主线程执行的代码都在main方法中。

  当产生垃圾时,收垃圾的动作,是不需要主线程来完成,因为这样,会出现主线程中的代码执行会停止,会去运行垃圾回收器代码,效率较低,所以由单独一个线程来负责垃圾回收。

  随机性的原理:因为cpu的快速切换造成,哪个线程获取到了cpu的执行权,哪个线程就执行。

  返回当前线程的名称:Thread.currentThread().getName()

  线程的名称是由:Thread—编号定义的。编号从0开始。

  线程要运行的代码都统一存放在了run方法中。

  线程要运行必须要通过类中指定的方法开启。start方法。(启动后,就多了一条执行路径)

  start方法:1)、启动了线程;2)、让jvm调用了run方法。

  创建线程的第一种方式:继承Thread ,由子类复写run方法。

  步骤:

    1,定义类继承Thread类;

    2,目的是复写run方法,将要让线程运行的代码都存储到run方法中;

    3,通过创建Thread类的子类对象,创建线程对象;

    4,调用线程的start方法,开启线程,并执行run方法。

  线程状态:

    被创建:start()

    运行:具备执行资格,同时具备执行权;

    冻结:sleep(time),wait()—notify()唤醒;线程释放了执行权,同时释放执行资格;

    临时阻塞状态:线程具备cpu的执行资格,没有cpu的执行权;

    消亡:stop()

  创建线程的第二种方式:实现一个接口Runnable。

  步骤:

    1,定义类实现Runnable接口。

    2,覆盖接口中的run方法(用于封装线程要运行的代码)。

    3,通过Thread类创建线程对象;

    4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。

      为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。

    5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。

      Ticket t = new Ticket();

      /*直接创建Ticket对象,并不是创建线程对象。

      因为创建对象只能通过new Thread类,或者new Thread类的子类才可以。

      所以最终想要创建线程。既然没有了Thread类的子类,就只能用Thread类。*/

      Thread t1 = new Thread(t); //创建线程。

      /*只要将t作为Thread类的构造函数的实际参数传入即可完成线程对象和t之间的关联

      为什么要将t传给Thread类的构造函数呢?其实就是为了明确线程要运行的代码run方法。*/

      t1.start();

  为什么要有Runnable接口的出现?

  1:通过继承Thread类的方式,可以完成多线程的建立。但是这种方式有一个局限性,如果一个类已经有了自己的父类,就不可以继承Thread类,因为java单继承的局限性。

    可是该类中的还有部分代码需要被多个线程同时执行。这时怎么办呢?

    只有对该类进行额外的功能扩展,java就提供了一个接口Runnable。这个接口中定义了run方法,其实run方法的定义就是为了存储多线程要运行的代码。

    所以,通常创建线程都用第二种方式。

    因为实现Runnable接口可以避免单继承的局限性。

  2:其实是将不同类中需要被多线程执行的代码进行抽取。将多线程要运行的代码的位置单独定义到接口中。为其他类进行功能扩展提供了前提。

    所以Thread类在描述线程时,内部定义的run方法,也来自于Runnable接口。

    实现Runnable接口可以避免单继承的局限性。而且,继承Thread,是可以对Thread类中的方法,进行子类复写的。但是不需要做这个复写动作的话,只为定义线程代码存放位置,实现Runnable接口更方便一些。所以Runnable接口将线程要执行的任务封装成了对象。

  //面试

       new Thread(new Runnable(){  //匿名
      public void run(){
        System.out.println("runnable run");
      }
    })
    {
      public void run(){
        System.out.println("subthread run");
      }
    }.start();  //结果:subthread run



    Try {
      Thread.sleep(10);
    }catch(InterruptedException e){}// 当刻意让线程稍微停一下,模拟cpu 切换情况。

    

  多线程安全问题的原因

发现一个线程在执行多条语句时,并运算同一个数据时,在执行过程中,其他线程参与进来,并操作了这个数据。导致到了错误数据的产生。

涉及到两个因素:

    1,多个线程在操作共享数据。

    2,有多条语句对共享数据进行运算。

    原因:这多条语句,在某一个时刻被一个线程执行时,还没有执行完,就被其他线程执行了。

  解决安全问题的原理:

    只要将操作共享数据的语句在某一时段让一个线程执行完,在执行过程中,其他线程不能进来执行就可以解决这个问题。

  如何进行多句操作共享数据代码的封装呢?

    java中提供了一个解决方式:就是同步代码块。

    格式:

    synchronized(对象) { // 任意对象都可以。这个对象就是锁。

      需要被同步的代码;

    }

3.2 同步

  好处:解决了线程安全问题。

  弊端:相对降低性能,因为判断锁需要消耗资源,产生了死锁。

  定义同步是有前提的:

    1,必须要有两个或者两个以上的线程,才需要同步。

    2,多个线程必须保证使用的是同一个锁。

同步的第二种表现形式:

  同步函数:其实就是将同步关键字定义在函数上,让函数具备了同步性。

  同步函数是用的哪个锁呢? 通过验证,函数都有自己所属的对象this,所以同步函数所使用的锁就是this锁。

当同步函数被static修饰时,这时的同步用的是哪个锁呢?

  静态函数在加载时所属于类,这时有可能还没有该类产生的对象,但是该类的字节码文件加载进内存就已经被封装成了对象,这个对象就是该类的字节码文件对象。所以静态加载时,只有一个对象存在,那么静态同步函数就使用的这个对象。这个对象就是 类名.class

同步代码块和同步函数的区别?

  • 同步代码块使用的锁可以是任意对象。

  • 同步函数使用的锁是this,静态同步函数的锁是该类的字节码文件对象。

    在一个类中只有一个同步,可以使用同步函数。如果有多同步,必须使用同步代码块,来确定不同的锁。所以同步代码块相对灵活一些。

  考点问题:请写一个延迟加载的单例模式?写懒汉式;当出现多线程访问时怎么解决?加同步,解决安全问题;效率高吗?不高;怎样解决?通过双重判断的形式解决。

  //懒汉式:延迟加载方式。

  当多线程访问懒汉式时,因为懒汉式的方法内对共性数据进行多条语句的操作。所以容易出现线程安全问题。为了解决,加入同步机制,解决安全问题。但是却带来了效率降低。

  为了效率问题,通过双重判断的形式解决。

class Single{
    private static Single s = null;
    private Single(){};
    public static Single getInstance(){ //锁是谁?字节码文件对象;
    if(s == null){
      synchronized(Single.class){
        if(s == null)
        s = new Single();
      }
    }
    return s;
    }
}

  同步死锁:通常只要将同步进行嵌套,就可以看到现象。同步函数中有同步代码块,同步代码块中还有同步函数。

  线程间通信:思路:多个线程在操作同一个资源,但是操作的动作却不一样。

    1:将资源封装成对象。

    2:将线程执行的任务(任务其实就是run方法。)也封装成对象。

  等待唤醒机制:涉及的方法:

    wait:将同步中的线程处于冻结状态。释放了执行权,释放了资格。同时将线程对象存储到线程池中。

    notify:唤醒线程池中某一个等待线程。

    notifyAll:唤醒的是线程池中的所有线程。

  注意:

    1:这些方法都需要定义在同步中。

    2:因为这些方法必须要标示所属的锁。你要知道 A锁上的线程被wait了,那这个线程就相当于处于A锁的线程池中,只能A锁的notify唤醒。

    3:这三个方法都定义在Object类中。为什么操作线程的方法定义在Object类中?

     因为这三个方法都需要定义同步内,并标示所属的同步锁,既然被锁调用,而锁又可以是任意对象,那么能被任意对象调用的方法一定定义在Object类中。

wait和sleep区别: 分析这两个方法:从执行权和锁上来分析:

wait:可以指定时间也可以不指定时间。不指定时间,只能由对应的notify或者notifyAll来唤醒。

sleep:必须指定时间,时间到自动从冻结状态转成运行状态(临时阻塞状态)。

wait:线程会释放执行权,而且线程会释放锁。

Sleep:线程会释放执行权,但不是不释放锁。

线程的停止:通过stop方法就可以停止线程。但是这个方式过时了。

    停止线程:原理就是:让线程运行的代码结束,也就是结束run方法。

    怎么结束run方法?一般run方法里肯定定义循环。所以只要结束循环即可。

    第一种方式:定义循环的结束标记。

    第二种方式:如果线程处于了冻结状态,是不可能读到标记的,这时就需要通过Thread类中的interrupt方法,将其冻结状态强制清除。让线程恢复具备执行资格的状态,让线程可以读到标记,并结束。

  —————————< java.lang.Thread >————

    interrupt():中断线程。

    setPriority(int newPriority):更改线程的优先级。

    getPriority():返回线程的优先级。

    toString():返回该线程的字符串表示形式,包括线程名称、优先级和线程组。

    Thread.yield():暂停当前正在执行的线程对象,并执行其他线程。

    setDaemon(true):将该线程标记为守护线程或用户线程。将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,

             Java 虚拟机退出。该方法必须在启动线程前调用。

    join:临时加入一个线程的时候可以使用join方法。

      当A线程执行到了B线程的join方式。A线程处于冻结状态,释放了执行权,B开始执行。

      A什么时候执行呢?只有当B线程运行结束后,A才从冻结状态恢复运行状态执行。

3.3 Lock接口

Lock接口:多线程在JDK1.5版本升级时,推出一个接口Lock接口。

  解决线程安全问题使用同步的形式,(同步代码块,要么同步函数)其实最终使用的都是锁机制   到了后期版本,直接将锁封装成了对象。线程进入同步就是具备了锁,执行完,离开同步,就是释放了锁。  在后期对锁的分析过程中,发现,获取锁,或者释放锁的动作应该是锁这个事物更清楚。所以将这些动作定义在了锁当中,并把锁定义成对象。

  所以同步是隐示的锁操作,而Lock对象是显示的锁操作,它的出现就替代了同步。

  在之前的版本中使用Object类中wait、notify、notifyAll的方式来完成的。那是因为同步中的锁是任意对象,所以操作锁的等待唤醒的方法都定义在Object类中。

  而现在锁是指定对象Lock。所以查找等待唤醒机制方式需要通过Lock接口来完成。而Lock接口中并没有直接操作等待唤醒的方法,而是将这些方式又单独封装到了一个对象中。这个对象就是Condition,将Object中的三个方法进行单独的封装。并提供了功能一致的方法 await()、signal()、signalAll()体现新版本对象的好处。

4.字符串

  < java.lang String字符串

  java中用String类进行描述。对字符串进行了对象的封装。这样的好处是可以对字符串这种常见数据进行方便的操作。对象封装后,可以定义N多属性和行为。

  如何定义字符串对象呢?String s = "abc";只要是双引号引起的数据都是字符串对象

  特点:字符串一旦被初始化,就不可以被改变,存放在方法区中的常量池中。

       String s1 = "abc"; // s1指向的内存中只有一个对象abc。
    String s2 = new String("abc"); // s2指向的内容中有两个对象abc、new 
    System.out.println(s1==s2);//fals
    System.out.println(s1.equals(s2));//true ,字符串中equals比较的是字符串内容是否相同。

4.1字符串的方法

1:构造方法:

将字节数组或者字符数组转成字符串。

        String s1 = new String();//创建了一个空内容的字符串。 
    String s2 = null;//s2没有任何对象指向,是一个null常量值。
    String s3 = "";//s3指向一个具体的字符串对象,只不过这个字符串中没有内容。
    //一般在定义字符串时,不用new。
    String s4 = new String("abc");
    String s5 = "abc"; 一般用此写
    new String(char[]);//将字符数组转成字符串。
    new String(char[],offset,count);//将字符数组中的一部分转成字符串。

2:一般方法:

      按照面向对象的思想:

2.1 获取:

      2.1.1:获取字符串的长度。length();

      2.1.2:指定位置的字符。char charAt(int index);

      2.1.3:获取指定字符的位置。如果不存在返回—1,所以可以通过返回值—1来判断某一个字符不存在的情况。

        int indexOf(int ch);//返回第一次找到的字符角标

        int indexOf(int ch,int fromIndex); //返回从指定位置开始第一次找到的角标

        int indexOf(String str); //返回第一次找到的字符串角标

        int indexOf(String str,int fromIndex);

        int lastIndexOf(int ch);

        int lastIndexOf(int ch,int fromIndex);

        int lastIndexOf(String str);

        int lastIndexOf(String str,int fromIndex);

      2.1.4:获取子串。

        String substring(int start);//从start位开始,到length()—1为止.

        String substring(int start,int end);//从start开始到end为止。//包含start位,不包含end位。

        substring(0,str.length());//获取整串

2.2 判断:

      2.2.1:字符串中包含指定的字符串吗?

        boolean contains(String substring);

      2.2.2:字符串是否以指定字符串开头啊?

        boolean startsWith(string);

      2.2.3:字符串是否以指定字符串结尾啊?

        boolean endsWith(string);

      2.2.4:判断字符串是否相同

        boolean equals(string);//覆盖了Object中的方法,判断字符串内容是否相同。

      2.2.5:判断字符串内容是否相同,忽略大小写。

        boolean equalsIgnoreCase(string) ;

2.3 转换:

      2.3.1:通过构造函数可以将字符数组或者字节数组转成字符串。

      2.3.2:可以通过字符串中的静态方法,将字符数组转成字符串。

        static String copyValueOf(char[] );

        static String copyValueOf(char[],int offset,int count);

        static String valueOf(char[]);

        static String valueOf(char[],int offset,int count);

      2.3.3:将基本数据类型或者对象转成字符串。

        static String valueOf(char);

        static String valueOf(boolean);

        static String valueOf(double);

        static String valueOf(float);

        static String valueOf(int);

        static String valueOf(long);

        static String valueOf(Object);

      2.3.4:将字符串转成大小写。

        String toLowerCase();

        String toUpperCase();

      2.3.5:将字符串转成数组。

        char[] toCharArray();//转成字符数组。

        byte[] getBytes();//可以加入编码表。转成字节数组。

      2.3.6:将字符串转成字符串数组。切割方法。

        String[] split(分割的规则—字符串);

      2.3.7:将字符串进行内容替换。注意:修改后变成新字符串,并不是将原字符串直接修改。

        String replace(oldChar,newChar);

        String replace(oldstring,newstring);

      2.3.8: String concat(string); //对字符串进行追加。

        String trim();//去除字符串两端的空格

        int compareTo();//如果参数字符串等于此字符串,则返回值 0;如果此字符串按字典顺序小于字符串参数,

                则返回一个小于 0 的值;如果此字符串按字典顺序大于字符串参数,则返回一个大于 0 的值。

4.2 StringBuffer字符串缓冲区

  构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。

  特点:

    1:可以对字符串内容进行修改。

    2:是一个容器。

    3:是可变长度的。

    4:缓冲区中可以存储任意类型的数据。

    5:最终需要变成字符串。

  容器通常具备一些固定的方法:

  1,添加。

    StringBuffer append(data):在缓冲区中追加数据。追加到尾部。

    StringBuffer insert(index,data):在指定位置插入数据。

  2,删除。

    StringBuffer delete(start,end);删除从start至end—1范围的元素

    StringBuffer deleteCharAt(index);删除指定位置的元素

    //sb.delete(0,sb.length());//清空缓冲区。

  3,修改。

    StringBuffer replace(start,end,string);将start至end—1替换成string

    void setCharAt(index,char);替换指定位置的字符

    void setLength(len);将原字符串置为指定长度的字符串

  4,查找。(查不到返回—1)

    int indexOf(string); 返回指定子字符串在此字符串中第一次出现处的索引。

    int indexOf(string,int fromIndex);从指定位置开始查找字符串

    int lastIndexOf(string); 返回指定子字符串在此字符串中最右边出现处的索引。

    int lastIndexOf(string,int fromIndex); 从指定的索引开始反向搜索

  5,获取子串。

    string substring(start); 返回start到结尾的子串

    string substring(start,end); 返回start至end—1的子串

  6,反转。

    StringBuffer reverse();字符串反转

4.3 StringBuilder字符串缓冲区

  JDK1.5出现StringBuiler;构造一个其中不带字符的字符串生成器,初始容量为 16 个字符。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。

  方法和StringBuffer一样;

  StringBuffer 和 StringBuilder 的区别:

    StringBuffer线程安全。

    StringBuilder线程不安全。

    单线程操作,使用StringBuilder 效率高。

    多线程操作,使用StringBuffer 安全。

           StringBuilder sb = new StringBuilder("abcdefg");
      sb.append("ak");  //abcdefgak
      sb.insert(1,"et");//aetbcdefg
      sb.deleteCharAt(2);//abdefg
      sb.delete(2,4);//abefg
      sb.setLength(4);//abcd
      sb.setCharAt(0,'k');//kbcdefg
      sb.replace(0,2,"hhhh");//hhhhcdefg 

      //想要使用缓冲区,先要建立对象。
      StringBuffer sb = new StringBuffer();
      sb.append(12).append("haha");//方法调用链。
      String s = "abc"+4+'q';
      s = new StringBuffer().append("abc").append(4).append('q').toString();

     

class  Test{
    public static void main(String[] args) {
      String s1 = "java";
      String s2 = "hello";
      method_1(s1,s2);
      System.out.println(s1+"...."+s2); //java....hello
      StringBuilder s11 = new StringBuilder("java");
      StringBuilder s22 = new StringBuilder("hello");
      method_2(s11,s22);
      System.out.println(s11+"—————"+s22); //javahello—————hell
    }

    public static void method_1(String s1,String s2){
      s1.replace('a','k');
      s1 = s2;
    }
    public static void method_2(StringBuilder s1,StringBuilder s2){
      s1.append(s2);
      s1 = s2;
    }
  }

5.封装 

基本数据类型对象包装类:是按照面向对象思想将基本数据类型封装成了对象。

  好处:

    1:可以通过对象中的属性和行为操作基本数据。

    2:可以实现基本数据类型和字符串之间的转换。

  关键字 对应的类名

    byte Byte

    short Short paserShort(numstring);

    int Integer 静态方法:parseInt(numstring)

    long Long

    float Float

    double Double

    char Character

    Boolean Boolean

    基本数据类型对象包装类:都有 XXX parseXXX 方法

    只有一个类型没有parse方法:Character ;

5.1 Integer对象

  数字格式的字符串转成基本数据类型的方法:

    1:将该字符串封装成了Integer对象,并调用对象的方法intValue();

    2:使用Integer.parseInt(numstring):不用建立对象,直接类名调用;

  将基本类型转成字符串:

    1:Integer中的静态方法 String toString(int);

    2:int+"";

  将一个十进制整数转成其他进制:

    转成二进制:toBinaryString

    转成八进制:toOctalString

    转成十六进制:toHexString

      toString(int num,int radix);

  将其他进制转换十进制:

    parseInt(string,radix); //将给定的数转成指定的基数进制;

  在jdk1.5版本后,对基本数据类型对象包装类进行升级。在升级中,使用基本数据类型对象包装类可以像使用基本数据类型一样,进行运算。

    Integer i = new Integer(4); //1.5版本之前的写法;

    Integer i = 4; //自动装箱,1.5版本后的写法;

    i = i + 5;

    //i对象是不能直接和5相加的,其实底层先将i转成int类型,在和5相加。而转成int类型的操作是隐式的。自动拆箱:拆箱的原理就是i.intValue();i+5运算完是一个int整数。如何赋值给引用类型i呢?其实有对结果进行装箱。

    Integer c = 127;

    Integer d = 127;

    System.out.println(c = = d); //true

    //在装箱时,如果数值在byte范围之内,那么数值相同,不会产生新的对象,也就是说多个数值相同的引用指向的是同一个对象。