Java基础回顾

本文全面介绍了Java的基础知识,包括JDK下载与环境配置、Java注释、类与对象的概念及应用、八大基础数据类型、Java的三大特性(封装、继承、多态)、接口与抽象类的区别、变量类型详解等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

序言

在很早之前就想出一篇基础方面的总结,但是思路一直不清晰,还是想在巩固一下这方面毕竟基础还是很重要的。接下来我将从什么是java列出,话不多说直接low它

什么是Java

Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程

Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 [2] 。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等

JDK下载与环境配置

下载路径:jdk1.8下载
现在jdk已经是属于oracle旗下的产品了所以可以在官网中下载即可,下载后安装,安装具体步骤我就不过多描述,与安装其他产品很相似比较简单。
来说一下jdk环境的配置
环境配置
1.找到电脑中高级系统中的环境配置,在我的电脑中右击找到即可,在系统变量中创建一个名为JAVA_HOME的变量名,变量值填入你安装好后的jdk路径即可,样式图如下:

在这里插入图片描述
在Path变量中增加两项,分别是“%JAVA_HOME%\bin”“%JAVA_HOME%\jre\bin”
在这里插入图片描述

查看信息
查看是否安装成功,点击win+R之后cmd输入命令java -version即可查看jdk版本信息
在这里插入图片描述

安装工具

目前来说在行业中使用比较火的两款工具分别为eclipse与idea,我在之前写过一篇idea的安装教程,eclipse可能现在用的稍微会比idea少一些我也就不过多的说明了idea安装跳转路径

Java注释

Java 支持三种注释方式。前两种分别是 // 和 /* /,第三种被称作说明注释,它以 /* 开始,以 */结束。
说明注释允许你在程序中嵌入关于程序的信息。你可以使用 javadoc 工具软件来生成信息,并输出到HTML文件中。说明注释,使你更加方便的记录你的程序信息。

//这是一个单行注释

/*这是一个多行注释*/

/*
*@author 藤井大叔
*@packageName 这是一个文档注释
*/

类与对象

类:类是一个模板,它描述一类对象的行为和状态
对象:对象是类的一个实例,有状态和行为
打比喻

一个人(Persion.java)
每个人身上都有很多特征吧,比如说黄种人、白种人、黑种人,这是一个品种,
那我给一个字段叫品种(private String variety)
那么得出以下实现,那我在给一个特征叫身高,我给啥特征直接往下加入即可了
public class persion{
	//品种
	private String variety;
	//身高
	private double stature;
		//......
}

这样是不是就很好理解了,把人比作一个类,把品种与身高等等特征去对这个类实例化(对象),在将它们描述出来

八大基础数据类型

  1. 布尔型
    boolean
  2. 整形
    int、short、long
  3. 浮点型
    float、double
  4. 字符型
    char

Java三大特性

封装

封装即是对一个类的信息隐藏在类的内部,只能通过该类的方法去访问隐藏的信息,好处在于直接通过操控类对象来达到目的,不需要对具体实现十分了解,不但方便还对该类的信息起到保护作用,一般使用封装是将该类的属性限制为private,具体的我下面有一张访问权限表格供参考

访问修饰符本类同包子类其他
private
default
protected
public

案例:

User.java

package test;
/**
 * @Date 2021/7/22 15:58
 * @Version SpringBoot 2.2.2
 * @packageName 封装
 */
public class User {
        //private代表这个属性只可以在本类使用
        //属性都是可以先赋予默认值的,公式: 访问修饰符 类型 属性 = 默认值;即可
        private String username ="admin";
        private String password;

        //public代表所有的将可直接访问
        public int age = 10;

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        //这里是get方法,就是我调用的时候返回的是什么那就是什么。比如我getUsername方法是返回的username的内容,那就是返回我刚
        //添加的默认值
        public String getPassword() {
            return "123456";
        }

        public void setPassword(String password) {
            this.password = password;
        }
}
Mian.java

package test;

/**
 * @Date 2021/7/22 16:13
 * @Version SpringBoot 2.2.2
 * @packageName
 */
public class Main {

    public static void main(String[] args) {
        User userTest = new User();
        //age
        System.out.println("age输出:"+userTest.age);
        //username
        System.out.println("username输出:"+userTest.getUsername());
        //password
        System.out.println("password输出:"+userTest.getPassword());
    }
}
//返回信息
age输出10
username输出admin
password输出123456

上面我所做的案例中含有private与public的案例,大家细看一下应该可以知道我在mian方法中是找不到username与password的属性,只能通过他们的方法来获取信息,这就达到了我上面所描述的目的了

继承

这里我做一个比喻,儿子是老子的子辈,老子是儿子的父辈分是吧,那么这两种关系就是父子关系,当儿子的肯定是会遗传一些父子上基因吧,这就是所谓儿子继承父辈的关系,但是在Java中只能是单继承,但是可以多实现这个我下面会在接口讲解中说到,回到原题,根据上面这个比喻拿java说继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。,下面我做一个案例

Elder.java

package test;
/**
* @Date 2021/7/22 15:58
* @Version SpringBoot 2.2.2
* @packageName 继承
*/
父类
public class Elder {
       private String name = "张三";
       private int age =10;


   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 void introduce(){
       System.out.println("方法是在Elder类,但是实例对象的是Son,因为我的东西都可以给Son类使用");
   }
}

Son.java

package test;
/**
* @Date 2021/7/22 16:45
* @Version SpringBoot 2.2.2
* @packageName 继承
*/
子类
public class Son extends Elder {

   private String gender ="女";

   public String getGender() {
       return gender;
   }

   public void setGender(String gender) {
       this.gender = gender;
   }
}

mian方法:
public static void main(String[] args) {
       //因为Son类继承了Elder,就如我刚刚比喻老子的基因还是传给儿子了是吧
       Son son = new Son();
       son.introduce();
       System.out.println("我叫"+son.getName()+"今年"+son.getAge()+"岁了。"+"我的性别是:"+son.getGender());
   }

输出
方法是在Elder,但是实例对象的是Son,因为我的东西都可以给Son类使用
我叫张三今年10岁了。我的性别是:

在上面的案例中可发现我在main()方法中并未对父类做任何操作,而是全部做的子类操作。但是还是可以使用到父类属性与方法,因为我在之类继承了父类的关系达到了目的,认真观察可以看到在子类中有一个extends关键字,这个就是继承的关键字,总的意思来说就是你的是我的,我的还是我的。

多态

还是拿父子辈分关系来做比喻吧,在我国现都开放三胎政策的时代一个老子不可能只会有一个儿子吧,特别是在以前生的子孙特多,不过也是在爷爷辈分的那个时代了,一家生7、8个的我都听说过,但是既然儿子多了,虽然基因是由父辈传承但是每个儿子的生活习性还是有所不同的吧,多态也是这个意思,在Java中的说法就是多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作

接口与抽象类

既然说到了多态,那么我们就顺道性的把这两个内容块也在这里说明一下吧,首先我说一下他们两个之间具体的区别

接口与抽象类的区别
  1. 抽象类是在该类使用了abstract关键字,必须要之类继承后才能实现抽象类,接口要被类实现才能使用接口中的所有方法,上面我们收到继承是extends关键字,那么实现关键字是implements
  2. 抽象类只能是被单继承,而接口可以多实现
  3. 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量

实现多态

还是一样的,现在爸爸又出生了几个,有小红、小明、小刚。下面来做一个具体实现看啊可能
为了展示一下接口的使用,我这边创建一个父亲接口

/**
 * @Date 2021/7/22 18:17
 * @Version SpringBoot 2.2.2
 * @packageName 父辈
 */
public interface Elder {

    void add();
}

/**
 * @Date 2021/7/22 18:18
 * @Version SpringBoot 2.2.2
 * @packageName 子1
 */
public class test1 implements Elder {


    @Override
    public void add() {
        System.out.println("我叫小明,今年24岁了,我的父亲是Elder");
    }
}

/**
 * @Date 2021/7/22 18:18
 * @Version SpringBoot 2.2.2
 * @packageName 子2
 */
public class test2 implements Elder {


    @Override
    public void add() {
        System.out.println("我叫小红,今年18岁了,我的父亲是Elder");
    }
}

/**
 * @Date 2021/7/22 18:18
 * @Version SpringBoot 2.2.2
 * @packageName 子3
 */
public class test3 implements Elder {


    @Override
    public void add() {
        System.out.println("我叫小刚,今年12岁了,我的父亲是Elder");
    }
}

/**
 * @Date 2021/7/22 18:24
 * @Version SpringBoot 2.2.2
 * @packageName 实现类
 */
public class Main {

    public static void main(String[] args) {
        //小明
        Elder elder = new test1();
        elder.add();
        //小红
        Elder elder1 = new test2();
        elder1.add();
        //小刚
        Elder elder2 = new test3();
        elder2.add();

    }
}

输出结果
我叫小明,今年24岁了,我的父亲是Elder
我叫小红,今年18岁了,我的父亲是Elder
我叫小刚,今年12岁了,我的父亲是Elder

同样是一个父亲,但是每个子辈的信息都是不同的
接口比起继承的最大区别就是多实现与单继承,当我们写了多个接口方法时,直接在实现后面用逗号隔开即可

实现多态的方法

1.实现接口
2.重写

Override与Overload的区别

重写

什么叫重写(Override),重写就是方法方法与参数都与父类相同的称之为重写,比如我上面的继承中的,直接把方法重写到子类即可,具体如下实现

@Override
public void introduce(){
     System.out.println("我现在是在Son类啦");
   }
}

super关键字

下面再来说一下super关键字的使用,这个关键字的作用就是当需要在子类中调用父类的被重写方法时,要使用 super 关键字。调用之后在继承执行输出应该是如下

方法是在Elder,但是实例对象的是Son,因为我的东西都可以给Son类使用
我现在是在Son类啦
我叫张三今年10岁了。我的性别是:

用法:

@Override
public void introduce(){
     super.introduce();
     System.out.println("我现在是在Son类啦");
}

这样就可以将父类的具体实现也执行出来了

重载

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载

public Elder(String name){
        this.name = name;
    }

public Elder(String name,int age){
        this.name = name;
        this.age = age;
    }

在三大特性中我讲述的内容对于初学者来说可能还是居多的,我下面整理一下。主要是讲了以下三大点
1.三大特性:封装、继承、多态的用法以及意思
2.抽象类与接口之间的区别与使用
3.重载与重写的区别与用法

Java变量类型

局部变量与成员变量

两者之间的区别
1.在类中的位置不同(成员变量是在类中方法外,而局部变量是在方法代码块中或者方法参数列表中)
2.在内存的位置也不同(成员变量是在堆中,而局部变量是在栈中)
3.生命周期不同(成员变量是随着对象的创建而存在,随着对象的消失而消失,但是局部变量是随着方法的调用或者代码块的执行而存在,随着方法或代码块的执行完毕而消失)
4.初始值不同(成员变量又默认初始值,而局部变量需要自定义初始值,否则编译会报错)

static关键字与final关键字

static

static关键字的基本作用一句话来描述就是:方便在没有创建对象的情况下来进行调用(方法/变量)。很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能,下面我做一个小案例来证明一下更直观的表现static的作用

package uncletj;

/**
 * @Date 2021/7/26 15:00
 * @Version SpringBoot 2.2.2
 * @packageName static关键词测试
 */
public class Demo {


    String name = "张三";

    static String name1 = "李四";

    public void test(){
        System.out.println("未使用static关键词:测试一");
    }

    public static void test2(){
        System.out.println("使用了static关键词:测试二");
    }

    public static void main(String[] args) {
        //测试一
        Demo demo = new Demo();
        demo.test();
        //测试二
        test2();

        System.out.println("未使用static关键词的名字叫:"+demo.name);
        System.out.println("使用了static关键词的名字叫"+name1);
    }
}
//执行输出
未使用static关键词:测试一
使用了static关键词:测试二
未使用static关键词的名字叫:张三
使用了static关键词的名字叫李四
final

1.被final修饰的类不能被继承
在这里插入图片描述
2.被修饰的方法不能重写,但是该方法还是可以被继承
在这里插入图片描述
在这里插入图片描述
3.如果用来修饰的是基本数据类型的话那么这个值就是最终值,不可以被修改。如果引用时类的成员变量,则必须当场赋值,否则编译会报错

/**
 * @Date 2021/7/26 15:00
 * @Version SpringBoot 2.2.2
 * @packageName final关键词测试
 */
public class Demo {

	//成员变量必须赋予初始值,不然会编译出错
    static final int age=24;

    static int age2 = 24;

    public static void main(String[] args) {
    	//age已经被修饰未常量值说明不可修改,修改会编译报错
        //age = 25;
        age2 = 25;
        System.out.println(age);
        System.out.println(age2);
    }
}
//执行结果
24
25

4.如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改
在这里插入图片描述

条件语句、选择结构与循环语句

条件语句

if

public static void main(String[] args) {
        Scanner i = new Scanner(System.in);
        System.out.println("请选择你喜欢的类型:");
        int a = i.nextInt();
        if (a==1){
            System.out.println("猛男");
        }
        if (a==2){
            System.out.println("小姐姐");
        }
        if (a==3){
            System.out.println("泰国人妖");
        }
    }

else-if

public static void main(String[] args) {
        Scanner i = new Scanner(System.in);
        System.out.println("请选择你喜欢的类型:");
        int a = i.nextInt();
        if (a==1){
            System.out.println("猛男");
        } else if (a==2){
            System.out.println("小姐姐");
        }else if(a==3){
            System.out.println("泰国人妖");
        }
    }

else

public static void main(String[] args) {
        Scanner i = new Scanner(System.in);
        System.out.println("请选择你喜欢的类型:");
        int a = i.nextInt();
        if (a==1){
            System.out.println("猛男");
        } else if (a==2){
            System.out.println("小姐姐");
        }else if(a==3){
            System.out.println("泰国人妖");
        }else{
            System.out.println("你选择的是男人婆");
        }
    }
//执行0之后输出
你选择的是男人婆

选择结构

选择结构主要是由switch关键字获取你输入的类型值返回不同的语句,在switch中有3个关键字为return、break、continue,这三个不同的作用分别为如下

return、break、continue的区别

  1. return关键字并不是专门用于跳出循环的,return的功能是结束一个方法。 一旦在循环体内执行到一个return语句,return语句将会结束该方法,循环自然也随之结束。与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内
  2. continue的功能和break有点类似,区别是continue只是中止本次循环,接着开始下一次循环。而break则是完全中止循环
  3. break用于完全结束一个循环,跳出循环体。不管是哪种循环,一旦在循环体中遇到break,系统将完全结束循环,开始执行循环之后的代码。 break不仅可以结束其所在的循环,还可结束其外层循环。此时需要在break后紧跟一个标签,这个标签用于标识一个外层循环。Java中的标签就是一个紧跟着英文冒号(:)的标识符。且它必须放在循环语句之前才有作用
public static void main(String[] args) {
        Scanner i = new Scanner(System.in);
        System.out.println("请选择你喜欢的类型:");
        int a = i.nextInt();
        switch (a){
            case 1:
                System.out.println("猛男");
                break;
            case 2:
                System.out.println("小姐姐");
                break;
            case 3:
                System.out.println("泰国人妖");
                break;
            default:
                System.out.println("你选择的是男人婆");
                break;
        }
    }

循环语句

for循环

先判断,再执行

public static void main(String[] args) {
        for (int i=0;i<10;i++){
            System.out.println("我正在执行第"+(i+1)+"次输出");
        }
    }
执行输出
我正在执行第1次输出
我正在执行第2次输出
我正在执行第3次输出
我正在执行第4次输出
我正在执行第5次输出
我正在执行第6次输出
我正在执行第7次输出
我正在执行第8次输出
我正在执行第9次输出
我正在执行第10次输出

下面我给一个简单的测试题,我想要得到1~10以内的总和,我该怎么实现?先看看死办法

int a =0+1+2+3+4+5+6+7+8+9+10;
int b = 0;
System.out.println("a的总和为"+a);
a的总和为:55

//这样的执行结果确实可以得到准确值,但是我这边在除一个测试题11000或者110000的你也这样写吗
//试试用for循环看看

public static void main(String[] args) {
        int b =0;
        for (int c =0;c<10;c++){
            b +=c+1;
        }
        System.out.println("b的总和为"+b);
    }
//执行结果为
b的总和为:55

当然我们还可以做更多的事情,像我们小学学的奇数偶数之和的运算也是可以通过for循环求出来的,具体实现如下

public static void main(String[] args) {
        int b =0;
        int d =0;
        for (int c =0;c<=10;c++){
            if (c%2==0){
                b=b+c;
            }
        }
        for (int c =0;c<=10;c++){
            if (c%2==1){
                d=d+c;
            }
        }
        System.out.println("b的偶数和为"+b);
        System.out.println("d的奇数和为"+d);
    }
//执行输出
b的偶数和为30
d的奇数和为25

在程序设计中我可以使用多种方式来实现这到题目,下面我将介绍while循环

while循环

public static void main(String[] args) {
        int i = 0;
        int sum =0;
        while (i<=10){
            if (i%2==0){
                sum+=i;
            }
            i++;
        }
        System.out.println("1~10以内的偶数之和为:"+sum);
    }
执行结果:
1~10以内的偶数之和为:30

偶数是不是和上面for循环的是一样的,说明想要实现同样的结果我们可以通过不同的方式去实现,这也是编程中最重要的思想,不能盲目的记代码,而是懂得什么场景可以通过什么方式去实现我们自己想到得到的结果,下面我们再来看一下与while循环相似的do-while循环的实现

do-while

do-while与while不同的是它是先执行后判断,下面看看是如何实现的,这边还是参考去取偶数值来做一个测试

public static void main(String[] args) {
        int i = 0;
        int sum =0;
        do {
            if (i%2==0){
                sum+=i;
            }
            i++;
        }while (i<=10);
        System.out.println("1~10以内的偶数之和为:"+sum);
    }
执行结果:
1~10以内的偶数之和为:30

foreach循环

这个循环一般是针对数据来做实现,使用foreach循环遍历数组和集合时,无需获得数组和集合的长度,无须根据索引来访问数组元素和集合元素,foreach循环自动遍历数组和集合的每一个元素。下面我们也做一个测试来看看foreac的实战

import java.util.*;

/**
 * @Date 2021/7/26 15:00
 * @Version SpringBoot 2.2.2
 * @packageName 循环语句
 */
public class Demo {

    private static final String name ="李四";
    private static final String age ="24";
    private static final String gender ="男";



    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("张三");
        list.add(24);
        list.add("男");

        Map<String,String> map = new HashMap<>();
        map.put("name",name);
        map.put("age",age);
        map.put("gender",gender);

        System.out.println("使用foreach实现list集合输出:");
        //循环list数组
        for (Object persion:list) {
            System.out.println(persion);
        }

        //一个空的输出语句可以让两个执行中间隔开一点距离,当然在java中也可以使用\n实现
        System.out.println();

        //这个是使用了foreach+lambda表达式来循环map集合
        System.out.println("使用foreach实现map集合数组");
        map.forEach((k,v)->{
            System.out.println(k+":"+v);
        });
    }
}
执行输出结果:
使用foreach实现list集合输出:
张三
24
男

使用foreach实现map集合数组
gender:男
name:李四
age:24

枚举的使用

什么是枚举

枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。本质就是,一个类里定义几个静态变量,每个变量都是这个类的实例

使用

一般什么场景会使用到枚举,比如我们需要大部分场景下返回一些通用词的情况下我们可以定义一个枚举类来达到目的,那么什么时候会返回通用词呢,例如我们的异常返回、格式返回、以及一些固定返回值的时候就可以定义枚举类,具体实现我在下面进行展示一下

public class Demo2 {
    public enum ExceptionEnum{
        SUCCESS,
        ERROR;
    }
    public static void main(String[] args){
        ExceptionEnum a = ExceptionEnum.SUCCESS;
        switch (a){
            case ERROR:
                System.out.println("失败");
                break;
            case SUCCESS:
                System.out.println("成功");
                break;
        }
    }
}
//执行输出
成功

String、StringBuilder、StringBuffer之间的区别

String的介绍以及使用

首先我们先来简单使用一下看看,其实在上面我们也是用到了,不过没有做一个详细的介绍,String是一个字符串,他是一个常量类型的,不是基础数据类型之一,使用方法如下

String name = "张三";
System.out.println(name);

//执行输出
张三

下面我们来看看String的源码分析一下内部具体是干嘛的,当然这里根据案例发现已经是输出字符串类型的了但是String还有一些操作也是可以使用的,具体如下
在这里插入图片描述
首先可以看出来String是一个常量类型,说明不允许被继承。并且实现了Serializable、Comparable 、CarSequence这个三个接口,具体部分方法我都有实现过,具体如下

public static void main(String[] args){
        String name = "张三";
        //输出字符串
        System.out.println(name);
        //字符串长度
        System.out.println(name.length());
        //下标从0开始,所以第一个是三
        System.out.println(name.charAt(1));
        //返回的字符串中第一次出现的位置
        System.out.println(name.indexOf("张"));
        //判断是否出现该字符
        System.out.println(name.contains("一"));
        //字符是否为空
        System.out.println(!name.isEmpty());
        //判断字符是否相同
        System.out.println(name.equals("张三"));
    }
//执行输出
张三
20
false
true
true

StringBuffer的介绍以及使用

StringBuffer对象的初始化不像String类的初始化一样,Java提供的有特殊的语法,而通常情况下一般使用构造方法进行初始化,从下面的源码可以看出来StringBuffer也是常量类型,不可以被继承,并且实现了Serializable接口,说明是线程安全的
在这里插入图片描述

public static void main(String[] args){
        StringBuffer name = new StringBuffer("张三");
        //输出StringBuilder
        System.out.println(name);
        //追加字符
        name.append("王老五");
        //输出初始值加追加值
        System.out.println(name);
        //删除指定字符
        name.delete(2,5);
        //执行删除之后的字符
        System.out.println(name);
        //指定某地标插入值
        name.insert(2,"王老五");
        System.out.println(name);
        //字符反转
        System.out.println(name.reverse());
    }
//执行输出
张三
张三王老五
张三
张三王老五
五老王三张

StringBuilder介绍以及使用

String 对象是不可改变的。每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的 String 对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用 System.Text.StringBuilder 类,具体实现我们来做一个案例

StringBuilder str = new StringBuilder("张三");
        System.out.println("张三");
        System.out.println(str.append(",你好!"));
        System.out.println(str.delete(2,6));
        System.out.println(str.insert(2,",你好!"));
        System.out.println(str.deleteCharAt(5));
        System.out.println(str.reverse());
//执行输出
张三
张三,你好!
张三
张三,你好!
张三,你好
好你,三张

三者之间的区别

  1. String使用字符数组保存字符串,因为有“final”修饰符,所以可以知道string对象是不可变的,也就可以理解为常量,显然线程安全
  2. StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的
  3. StringBuilder并没有对方法进行加同步锁,所以是非线程安全的
  4. StringBuilder与StringBuffer有公共父类AbstractStringBuilder,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法

执行速度相比较

我这边就直接做一个小案例,然后大家看看执行所需的时间即可看出三者之间的执行速度

------------------------------------------------------------------------------------
String执行测试时间

long time = new Date().getTime();
        //字符串
        String name = "张三";

        for (int i=0;i<10000;i++){
            name +=+i;
        }
        System.out.println("String使用的时间"+(System.currentTimeMillis()-time)/1000.0+"s");

执行输出
String使用的时间0.308s
------------------------------------------------------------------------------------
StringBuffer执行测试时间

long time = new Date().getTime();
        //字符串
        StringBuffer name = new StringBuffer("张三");

        for (int i=0;i<10000;i++){
            name.append(i);
        }
        System.out.println("StringBuffer使用的时间"+(System.currentTimeMillis()-time)/1000.0+"s");

执行输出
StringBuffer使用的时间0.003s
------------------------------------------------------------------------------------
StringBuilder执行测试时间

long time = new Date().getTime();
        //字符串
        StringBuilder name = new StringBuilder("张三");

        for (int i=0;i<10000;i++){
            name.append(i);
        }
        System.out.println("StringBuilder使用的时间"+(System.currentTimeMillis()-time)/1000.0+"s");

执行输出
StringBuilder使用的时间0.001s

从上方看出同样方法测试,但是每个执行的速度都是不相同的,由此得出,速度由
StringBuilder——StringBuffer——String

若要前行,就要离开你现在停留的地方!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

藤井大叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值