复习专栏之---java语言(基础)

1. 编程基础及java背景

  • 计算机行业的发展,核心从未改变过,计算机所能识别的终究只有“0”和“1”,我们只是在开发更多易于书写和运行速度快,应用层面不同的编程语言,操作计算机的都是编程语言,从最初的机器语言,到幼稚的汇编语言,一直到现在各种高级语言。每种语言的产生都是为了适用一个特定的环境,因此,每种语言都必有其特征,也就是长处。
  • 1.2版本是java历史上最重要的一代版本,1998年发布,添加了swing 和 集合框架,并且在此时对类库进行了分类:j2se(基础,小程序) j2ee(网站开发) j2me(嵌入式开发,现已过时)
  • java的优势
    a:可移植性,跨平台,因为他使用JVM虚拟机,其实是因为不同的系统有不同的java虚拟机,所以代码可以通用,其实现在看来只是所谓的移植性只是因为它事先准备好了各种版本的jvm吧。
    b:垃圾回收,自动垃圾回收,还可以主动传唤System.gc()
  • jdk是程序员编程需要使用的,可以书写代码及运行代码;jre是用户测试需要使用的,只能运行代码。
    JDK:java开发工具包,包含 开发工具 + jre
    JRE:java运行环境,包含JVM + 类库
  • java是 编译解释型的语言:javac是编译器,java是解释器,特点是预编译,而后各个平台调用各自的虚拟机将统一的.class文件识别为机器码,既可以移植,又可以保证可观的运行速度。
    其结构为:源代码(程序员写的单词啥的就叫源代码 后缀java的文件) --javac-》 字节码( 后缀class的文件,这也是其可移植性的原因,因为不同的cpu可以识别机器码是不同的,比如01在windows中是吃饭,在linux中可能就是喝水)-》 机器码
  • 编程的可移植性指的是编译后的代码可移植,而非源代码,任何语言的源代码都是可以直接复用的
  • JVM工作原理
    预编译:.java - .class
    运行:类加载 - 字节码检验 - 解释器 - 运行环境(jdk/jre)
    在这里插入图片描述
  • 注释(总是不熟练写注释,坏习惯)
    单行注释: //
    多行注释: /*     */
    文档注释: / **    */
  • 计算机的计量单位,计算机中最小的计量单位就是bit(比特),bit是表示信息的最小单位,是二进制数的一位包含的信息,不是0就是1。
    byte(字节)一般简写为B,一个字节就是8位二进制,除此之外都是1024进制。
    1B = 8bit
    1KB = 1024B
    1MB = 1024KB
    1GB = 1024MB
    1TB = 1024GB
  • 二进制数,左边第一位是高位,右边第一位是低位,高位代表着符号位,0是正数,1是负数;计算机中是以补码形式运算的
    原码:
    00000000-00000000-00000000-00000101     5
    10000000-00000000-00000000-00000101     -5
    反码:
    00000000-00000000-00000000-00000101     5
    11111111-11111111-11111111-11111010     -5
    补码:
    00000000-00000000-00000000-00000101     5
    11111111-11111111-11111111-11111011     -5
  • java标识符命名规则:
    1.由字母,数字,下划线_,$组成;
    2.不能以数字开头;
    3.不能是java的关键字;(保留字 const,goto)
    4.不能是字面值 true,false,null
    5.骆驼命名法:多个单词组成,第一个单词首字母小写,后边单词首字母大写,像骆驼一样,脑袋低,然后一个个凸起排列。
  • 日常使用:
    包名和项目名全部小写;
    类名首字母全部大写;
    常量全部字母大写;
    变量驼峰命名法;
    方法名驼峰命名法;
  • java数据类型:分为两种—八大基本数据类型(父类均为Number类)和引用数据类型(实质就是类、自己建的类便是引用数据类型
  • 基本数据类型:byte(1)、short(2)、int(4)、long(8)、float(4)、double(8)、char(2)、boolean(这个有些复杂,跟系统有关系,一般为1字节,会转成byte存储);整数int 小数double 字符char 计算机也会默认这三种,要表示其他要标示或强转;数据类型和科学计数法后缀表示,而进制用前缀表示
    long n5 = 55L;// long -> long 后缀 L
    float n1 = 11.1f;//float ->float 后缀 f F
    double n2 = 22.2d;//double -> double 后缀 d D
    //科学计数法 e以10为底
    double n3 = 11.1e50;
    //小数 可以表示 十六进制的数 但是 必须科学计数法
    // 而且此时只能用p以 2为底,不可以再用e(e在16进制代表14)
    double n4 = 0x11.1p20;
    int num1 = 0B101;//二进制 前缀 0B 0b
    int num2 = 017;// 八进制 0
    int num3 = 0x1f;//十六进制 0x 0X
  • 引用数据类型:字符串 String、类类型 class、 数组 [] 、 接口 interface 、 集合 、 文件;所有的类都是引用数据类型。
  • java中的关键字
    在这里插入图片描述
  • 什么是字符集什么是编码??
    以前一直混淆编码和字符集,以为unicode、ascll、utf啥的是一回事,在此记录一下!
    字符(Character)是文字与符号的总称,包括文字、图形符号、数学符号等。
    一组抽象字符的集合就是字符集(Charset);计算机要处理各种字符,就需要将字符和二进制内码对应起来,这种对应关系就是字符编码(Encoding)。
    制定编码首先要确定字符集,并将字符集内的字符排序,然后和二进制数字对应起来。根据字符集内字符的多少,会确定用几个字节来编码。
    每种编码都限定了一个明确的字符集合,叫做被编码过的字符集(Coded Character Set),这是字符集的另外一个含义。通常所说的字符集大多是这个含义。
    有哪些字符集ASCII(American Standard Code for Information Interchange,美国信息交换标准码)、ISO 8859(全称ISO/IEC 8859,是国际标准化组织(ISO)及国际电工委员会(IEC)联合制定的一系列8位字符集的标准,现时定义了15个字符集)、UCS(通用字符集(Universal Character Set,UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的字符编码方式,采用4字节编码,UCS包含了已知语言的所有字符)、Unicode(统一码、万国码、单一码,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求)、UTF(基于Unicode进行的更新,可变Unicode码,Unicode Translation Format)、汉字编码(中国人为了使用计算机创造的一种字符集)、ANSI( 使用2个字节来代表一个字符的各种汉字延伸编码方式,称为ANSI编码)、此外应该还有其他的
    有哪些编码方式:其实上述每种字符集都有对应的编码方式,常见的有ISO-8859-1GBKUTF-8等等很多。
    此处其实只是为了拓展基础知识,字符集和编码方式是两个概念!
  • 如何选择编码方式
    字符在保存时的编码格式如果和要显示的编码格式不一样的话,就会出现乱码问题。
    我们的Web系统,从底层数据库编码、Web应用程序编码到HTML页面编码,如果有一项不一致的话,就会出现乱码。
    所以,解决乱码问题说难也难说简单也简单,关键是让交互系统之间编码一致。
    在如此多种编码和字符集弄的我们眼花缭乱的情况下,我们只需选择一种兼容性最好的编码方式和字符集,让它成为我们程序子系统之间 交互的编码契约,那么从此恼人的乱码问题即将远离我们而去 – 这种兼容性最好的编码就是UTF-8! 毕竟GBK/GB2312是国内的标准,当我们大量使用国外的开源软件时,UTF-8才是编码界最通用的语言。
    此外还有一个原因,在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码(可变编码)。
    参考:Ascll、Unicode、UTF-8的区别和联系

2. 易错运算符

  • 加号:既可以表示连接也可以表示相加,并且经常会在同一行代码中既连接又相加。其运算方向是由左至右,只有参与运算的两者都是纯数字才可以相加,否则只能是连接。
    System.out.println(“hi”+22+33+“hello”); //hi2233hello
    System.out.println(22+33 +“hello”); //55hello
  • 左移和右移:左移和右移仅是对二进制进行操作。而且默认是4字节的二进制。其实无论任何移动是都二进制数整体移动,符号位也不特殊,同样随之移动。
    “<<”为左移:包括符号位整体左移n为,缺失部分用0填充(思考两个问题,负数左移是不是直接变成正数?一个数一直左移会变成什么?)
    “>>”为右移:包括符号位整体右移n位,符号位移动之前是什么则补充什么
    “>>>”为无符号右移:包括符号位整体右移n位,符号位不管移动之前是什么均用0补充(因此若原数为负数操作完后会很大)
    总结:左移和右移都是位运算,不管移动多少位都是一位一位的计算的,移动一位补一位,直至需要的位数,对于正数来说,右移和无符号右移没有任何区别,但是对于负数来说就会天差地别,究其原因就是因为负数右移时符号位会填充1,负数无符号右移时填充的是0。
    -1无论右移多少位还是-1而不是0,原因是计算机运算时用的是补码,符号位会一直补1
    位运算(左移右移)是计算机用补码运算的最好示例,并且位运算是计算机中运算速度最快的运算(因为位运算是对二进制数进行操作,任何操作的终点都是二进制数的操作,位运算一步到位,先天优势)
  • “ = ” 是赋值,“= =” 是相等,“!=” 是不等。
  • instanceof:判断的是对象与类的归属,也就是说两者最好是类或者引用数据类型,因此基本数据类型大部分无法使用instanceof,只有少数可以,且结果不一定准确,因为其父类是Number类!!!!
  • 取反:取反符号要慎重使用,记住----计算机的所有运算都是以补码进行的,不可以想当然。取反也是计算机使用补码进行运算的有效示例。在这里插入图片描述
  • 精度:所有的运算都是按照所有参与者中精度最高的数据类型进行统一运算的,小数 + 整数—>小数
  • 比较运算符:>(<)     ?     :
  • && || 和 & |区别:短路与否的区别

3. 条件循环

  • switch、 if
  1. switch只能判断等值。
    if 多用于 区间判断。
    并且switch等值判断时效率高,因此能等值时可以尽量等值判断而非区间判断
  2. if、else判断完后会自动break;
    switch判断的每层都需要手动break.如果没有break的话,一旦进入某一个case就会将之后的case全部执行,也就是说case本身没有break的作用。
  • for、   while、   do while:
    之前一直对for理解有问题,自己总结为for的执行可以理解为“V”字,先进行条件判断(不成立一次都不执行),条件成立执行完本次循环的所有语句,迭代值才会变化,也就说迭代语句可以理解为是隐形在循环体的最后一句,千万不要混淆迭代值的变化时刻。
    至于效率问题,非固定次数多用while,固定次数多用for。
  • 循环会用到的标签
    break:中断的意思,只能用在循环语句中,意为中断该循环结构,继续执行循环之后的代码,常用于循环中的if判断语句中,但无法单独用于if语句,因为if不是循环体,其核心就是用于循环体内,而不论循环体内是什么
    continue:继续的意思,只能用在循环语句中,意为继续下一层循环,跳过本次循环剩下的代码,常用于循环中的if判断语句中,但无法单独用于if语句,因为if不是循环体,其核心也是用于循环体内,而不论循环体内是什么
    ruturn:返回的意思,返回函数调用处,如果是类方法,返回类方法调用处,也就是中断该类方法后面的代码,继续执行,如果是主方法,则返回主方法调用出,也就是退出虚拟机了,相当于system.exit(0);
    System.exit(0):退出JVM

4. 初识JVM

  • 初识栈与堆在这里插入图片描述
  • 一个小例子
    在这里插入图片描述

5. 基础算法

  • 最大值
  • 冒泡
  • 选择
  • 插入
  • 二分查找法
//求最大数-随意选定一个值为max,之后依次与其他所有值进行比较,通过不断交换值选择出真正的max
int [] arr = {
   453,1222,7,89,3};
int max = arr[0];//第一个元素
int index = 0;     //定义一个存储下标的变量
int i = 1;
for(; i < arr.length ; i++) {
   
	if(max < arr[i]) {
    //1,2,3,4
		max = arr[i];
		index = i;//  记录下标
	}
}

//冒泡排序-相邻两位进行比较,每次比较可选出更大值,每轮选出一个最大值
int array [] = {
   1,3,2,0};
int len = array.length;
int temp;
for(int i = 0;i<len-1;i++){
   
	for(int j = 0;j<len-1-i;j++){
   
    	if(array[j]>array[j+1]){
   
			temp = array[j];
			array[j] = array[j+1];
			array[j+1] =temp;
         }
  	}
}
for(int i : array){
   
	System.out.println(i);
}

//选择排序-每一位与其他所有位置依次比较,每次比较可选出更大值,每轮选出一个最大值
int [] arr = {
   35,2543,11,4,6};
int temp;
for(int i = 0 ; i < arr.length - 1 ; i++) {
   //位置
	for(int j = i + 1; j < arr.length ; j ++) {
   //位置后的所有元素
		if(arr[i] > arr[j]) {
   
			temp = arr[i] ; 
			arr[i] = arr[j] ;
			arr[j] = temp;
		}
	}
}
for(int a : arr) {
   
	System.out.println(a);
}

//插入排序-从第二位开始,每个元素依次与前面的所有元素依次进行比较,根据大小值选择是否插入,每次插入可以让前面所有值都变为有序
//个人认为其实相比较而言,插入排序是比较难理解的,多次思考总结出了以下两点:
//第一,每一位元素是跟前面的所有元素进行比较,从第一位开始向后比较和从相邻位开始向前比较都是可行的,但是判断条件一定理清楚
//第二,每轮比较中其实只要插入一次后面就不必再循环了,一旦插入即有序了,即使再循环也没有意义。
int [] arr = {
   23,90,9,66,20};
int temp;
for(int i = 1; i < arr.length; i++) {
   //位置
	for(int j = 0; j < i; j++) {
   //前边的元素
		if(arr[i] < arr[j]) {
   
			temp = arr[i];//把此位置的元素存起来
			for(int k = i; k > j; k--) {
   
				//前边元素向后覆盖
				arr[k] = arr[k-1];
			}
			//把保存的位置元素覆盖到前边的元素
			arr[j] = temp;
			break;
		}
	}
}
for(int a :arr) {
   
	System.out.println(a);
}

//二分查找法-就一点,每次从有序集合的中间开始寻找,若给定的数组无序,则需要先将其处理成有序才可以使用二分查找法
int [] arr = {
   1,5,6,9,17}; //有序数组
Scanner scanner = new Scanner(System.in);
System.out.println("--输入一个数字:");
int num = scanner.nextInt();//
int start = 0;
int end = arr.length-1;
int middle = (start + end) / 2;
while(arr[middle] != num) {
   
	if(num > arr[middle]) {
   
		start = middle +1;
	}else{
   
		end = middle -1;
	}
	//起始位置>终止位置
	if(start > end) {
   
		middle = -1;
		break;
	}
	middle = (start + end) / 2;
}
System.out.println(middle);

6. 面向对象

  • 只有对象可以赋值为null,也就是相当于注销,比如Person person = new Person(); person = null;此时person就是空对象了,失去了引用,便成了垃圾,等待垃圾回收。
    因此,引用数据类型可以赋值为null,而基本数据类型是不可以的,究其根本,java的内存机制决定的,对象在内存中存储的是地址,赋值为null代表无引用,而基本数据类型内存中存储的是值,没有无引用那种状态。
  • 对象有四种状态:未初始化、null、有值、默认值(默认值只有在类中当成员变量时才会有,普通变量时jvm不会自动赋默认值
  • 基本数据只有三种状态:未初始化、有值、默认值(默认值只有在类中当成员变量时才会有,普通变量时jvm不会自动赋默认值
  • this关键字
    1.表示当前类对象,谁调用的该方法,this就指哪个对象;
    2.调用同类中的成员变量和方法;
    3.区分同名的成员变量和局部变量(加this代表调用成员变量,因为局部优先成员,其实和第二点作用有些相似);
    4.调用本类构造器,格式为this([参数]);(调用父类构造器为super([参数]);)。
  • 成员变量、局部变量
    成员变量:在类中定义的变量,归对象所有,是对象的一部分,随对象存在堆里,成员变量不会独立存储;
    局部变量:在方法中或代码块儿中定义的变量,只能在方法或代码块中使用,独立存储在堆中。
    两者区别:
    1)作用域:成员变量在整个类型中都有效;局部变量只在定义它的代码块中有效
    2)初始化:成员变量系统会自动初始化;局部变量系统不会自动初始化,需要自己初始化
    3)优先级:成员变量和局部变量同名,在局部变量作用域内,优先使用局部变量。
  • 传参
    之前理解的并不透彻,传参其实指的是复制变量,并且只复制栈中的值,与堆中的值无关。
    好好理解以下三张图
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    总结:传参其实是复制参数,不是汉语中的传递,汉语中的传递指的是一个人把一个东西给另一个人,东西只有一个,是所有人变了,而传参中的传递是复制一份,因为java运行时不同的方法(代码)会依次入栈,各自维护自己的参数。

7.java三大特征

  • 封装
  1. 定义:隐藏对象的属性和类中的实现细节,对外只提供公共的访问方式。
  2. 基本组件:
    构造器:public 类名(){} -----可以重载
    构造块:{} -----可以添加其他代码
    访问器:public void set(){} public 返回类型 get(){} —可以自定义调用范围
    作用均是:为类中的属性初始化,至于用途,因地制宜,再者就是调用顺序不一样。
  3. 成员变量初始化顺序:
    1.默认初始化;
    2.声明处初始化;
    3.构造块初始化;
    4.构造器初始化;
    (2,3执行顺序取决于代码中的书写顺序)
  4. 链式调用:其实就一句“return this”
    在这里插入图片描述
  5. stastic修饰符:个人认为也属于访问修饰符,只是不能修饰类而以,核心就一点,static修饰的事物,其归属权为类而不是对象,其存储位置为方法区而不是堆!!!此特征为本质,其余特征都是表象
  6. 静态变量:公用大桌子,希望有一个变量被所有对象共享使用。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    总结:静态变量之所以与实例变量不一样,就是因为存储在方法区(字节码文件(xx.class)、静态变量、常量、编译期可维护的都存在方法区),只要加载类虚拟机就会把类文件(xx.class)加载到虚拟机的方法区中,静态变量在类加载的时候就会初始化,只要加载这个类,随之虚拟机就会查看该类中有没有静态变量,如果有也加载到方法区中
  7. 静态方法:不需要创建实例对象即可调用的方法,静态方法中不能使用 this,和super.(它哪里有调用对象啊,可不就不能嘛)
  8. 静态块儿:
    clss 类{
         
       static{
         
         静态块:
         作用:初始化类。
               给静态变量赋值。
         执行:在类加载的时候自动执行。
       }
    }
    
    执行时间:
    1.静态块:类加载自动执行;
    2.构造块:new对象时,自动执行
    3.构造器():new 对象时调用,
    4.局部块:只有调用方法时执行;
  9. 随机数
    随机数一共有两种使用方式,一种是java.lang.Math.random,是Math类下的一个静态方法,直接输出一个随机数;一种是java.util.Random,是util下的一个类,实现了io接口,是创建的一个对象,需要继续调用Random下的方法才能输出随机数。后者可以定义随机种子,实现可控随机数,用于抽奖作弊等
    double n = Math.random();
    System.out.println(n);
    Random random = new Random(1);
    System.out.println(random.nextDouble());
    System.out.println(random.nextInt());
  • 继承
  1. super关键字:表示父类范围,其作用如下
    1.调用父类成员;成员的意思是属性和构造方法、实例方法等等
    2.可以区分同名的子类和父类的成员;
    3.调用父类构造。(若父类自定义了构造器,则子类不得不同样自定义构造器)
  2. 调用构造器
    创建子类对象时,一定会先调用父类构造(一直到Object类的构造),然后再调用子类构造。
    子类构造器中 ,如果没有显示调用super() 或者 this(),那么编译器一定会分配一个 super()。
    父类中显示定义了构造器,而且只有带参构造,那么子类构造器中 必须显示super(参数)调用父类带参构造。
  3. final修饰符,名“终态修饰符”
    修饰类时:此类不能被继承。目的—1)为了类的安全性;2)类中的方法有复杂的调用关系;3)此类是最终版本的类。
    修饰方法:此方法不能被重写。目的—所有子类使用的该方法只有一个版本,即此版本。
    修饰变量:即常量,此变量的值不能修改,只可赋值一次(但是,引用类型可以修改 属性的值)目的—1)数值安全;2)可维护;3)可读性好。命名规范—单词所有字母都大写,多个单词用下换线连接。
  • 多态
  1. abstract修饰符,抽象修饰符,无论抽象类还是抽象方法都是为了继承,抽象若无继承则毫无意义!
    抽象类:只约定类的抽象行为,没有具体实现相应的行为。
    1.抽象类不能创建对象,只能用多态的方法创建子类对象,抽象类就是为所有的子类提供了模板,存在意义就是被继承;
    2.必须通过 子类继承使用;
    3.普通的子类必须 实现(重写)父类中的所有抽象方法;抽象的子类除外;
    4.构造器不能是抽象;
    5.abstract 不能与 private, static, final一连用。显而易见,因为它必须被继承,不然毫无意义。
    6.抽象方法可以定义也可以不定义。
  2. 接口,是一组功能的封装,是一组公共的规则。和类的作用相同,神似抽象类
    语法:
    访问修饰符 interface 接口名{
         
        常量;
        抽象方法();//必须是抽象方法,也就是谁接口谁重写
        default 默认方法(){
         }
        static 静态方法(){
         }
        静态内部类型;//内部类,接口,枚举
     }
    
    注意:
    1.接口是不能创建对象的,同抽象类,只有其实现类可以创建对象,一般为多态创建
    2实现类必须实现接口中的所有抽象方法(抽象实现类除外,适配器设计模式就是因为接口的这一弊端);
    3.java规则是单继承性,多接口性,这也是接口存在的意义之一
    4.接口同样可以继承接口,并且可以多继承。
    5.接口中的成员都是public、抽象方法都是 abstract、常量是 public static final .
    多接口中有同名的方法:
    1.静态方法—用接口名区分;
    2.默认方法和抽象方法–反正需要重写,用谁的都没关系,也就是如果多继承的接口中全部都是重名的抽象方法,那就跟只继承一个没区别了,实现接口就是靠方法名区分不同方法的,因此尽量不要实现同名的接口。
  3. 抽象类和接口其实很像,都是定义一个集合或者规范而不具体实现,由子类自由发挥,比较不同的就是继承抽象类可以选择实现,而接口需要全部实现,由此还有一种设计模式是适配器模式。
  4. 多态就一句话,同一种引用类型,使用不同的实例而执行不同的操作。个人感觉其核心意义是为了传参方便,但由此导致了两个问题–类型转换和子类(实现类)中独特的功能被屏蔽了
    在这里插入图片描述
    在这里插入图片描述
    多态的存在形式有两种—父类引用创建子类对象以及接口引用创建实现类对象

8. 常用工具类

  • 操作数组:数组是引用数据类型,但是其创建不是常规意义的new,这个没有细究过其格式,但是一般来说对数组进行一些操作有两个类可以使用,Arrays和Array,刚看了看源码。
    Array类是public final class Array {},位于package java.lang.reflect;感觉像是数组的最高父类,其内部全是静态方法,包括数组的创建、修改元素、获取元素
    Arrays类是public class Arrays {},位于package java.util;且还导入了Array类,感觉更像数组的工具类,其内部也是静态方法,包括数组的排序、二分查找、类型转换、复制、填充、比较、tostring、、、
    因此,虽然实际上有两个工具类可以辅助数组,但是Array更侧重创建、Arrays侧重操作数组
  • 字符串
    字符串有三种,String、StringBuilder、StringBuffer,其中最常用的是String,另外两种算是进阶。String与其它两个最大的不同点就是,String是不可变的,一旦创建了String对象,它就是不可更改的了(因为底层是字符数组 private final char value[];),而其它两个都是可变的(StringBuffer与StringBuilder都继承自 AbstractStringBuilder类,在这个类中定义了一个char数组:char[] value;).再者String可以使用String s = "字符串"的格式初始化(因此可以存储在串池),其它两种不可以.而对于StringBuffer和StringBuilder,两者代码完全一样,只是StringBuffer的方法全部带有synchronized,说明它的线程安全,但是速度慢;反之StringBuilder线程不安全,但是速度快。
    其实总结来看,String是个特殊的对象,既可以构造器创建,又可以直接初始化,(取决于它的存储方式,既可以在堆也可以在常量池,其本质是一个字符数组,因此也决定了其不可变的特点)而StringBuilder、StringBuffer就是两个普通的对象,跟我们自己创建的类别无二致,调用构造器存储在堆中,没有在方法区中存储的能力。
    看懂下面的图就理解了String,至于两外两个没什么特殊,就不细说了
    在这里插入图片描述
    抛开存储机制,字符串(三种都是)其实就是一个普通的对象,因此操作字符串没有什么特殊性,就是直接调用其类方法进行处理即可,非静态方法需要其实例进行调用,静态方法既可以直接用类名调用,随着代码越写越多,很多东西会变得更加理所当然。操作数组之所以需要两个额外的类,是因为创建数组时不是通过创建对象的方式创建的,无法调用其类方法,只能引入额外的类,创建一些以数组为参数的方法,这是两个截然不同的概念。
  • 操作字符串
    其实本没有必要单独将操作字符串的,因为没什么特殊的,就是调用类方法操作对象实例罢了。既如此便总结一下易错方法吧。
  1. concat:名为字符串连接,其实我们都知道字符串是不可变的,因此其原理不是连接,而是创建一个新的字符串,并且还有一个有意思的事情,当我们用加号连接两个字符串时其实内部调用的是创建StringBuilder类而不是String类,这是JVM隐式实现的,其实也可以理解,既然必定要更改字符串,创建不可变的String岂不是浪费性能嘛
  2. substring:名为截取字符串,没什么特殊的,只是想提一句,java中涉及到起始时总是顾头不顾尾,即【起,终࿰
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lipviolet

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

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

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

打赏作者

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

抵扣说明:

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

余额充值