IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java(二)分支循环、数组、字符串、方法 -> 正文阅读

[Java知识库]Java(二)分支循环、数组、字符串、方法

一、分支循环

??Java中,除了普通的顺序结构外,特殊的结构有三种:分支结构、循环结构和跳转语句。

1.1 分支结构

??if、if-else、if-else if-else结构适合某个变量值在连续区间情况下的语句执行。
??如果某个变量值不是在连续区间的话,比如是整数,可以用switch。switch基本语法:

	switch(expression){
	    case value :
	       //语句
	       break; //可选
	    case value :
	       //语句
	       break; //可选
	    //...
	    default : //可选
	       //语句
	}

??switch-case结构与多种if结构作用相似,但是有局限性,其特点:

  • 1、JDK1.7之前的版本中,switch语句支持的数据类型有byte、short、int、char和枚举类型(即在整数类型中,唯独不支持long类型);在JDK1.7及以后的版本中,增加了对String类型的支持(编译后是把String转化为hash值,其实还是整数)。
  • 2、 用于等值判断
  • 3、break是每种case的结束标志,如无break则会继续走下个case。
  • 4、一般最后都会有个default,用来处理匹配不到任何case的情况。

??switch使用示例:

		int grade=80;
		switch(grade){
			case 60:
			case 70:
				System.out.println("你的成绩为60或70分");
				break;
			case 80:
				System.out.println("你的成绩为80分");
				break;
			default:
				System.out.println("你的成绩为60、70、80之外的分数");
				break;
		}

1.2 循环结构

??Java中循环结构有两种:

  1. for循环,有三部分:初始化操作、判断终止条件表达式及迭代部分。for循环一般用于循环次数已知的情况
  2. while循环,有两种:
	while(判断条件){
		循环体
	}
	
	do{
		循环体
	}while(判断语句);

??do-while先执行循环体语句,然后进行判断,也就是无论如何会先执行一次循环体语句。

1.3 跳转语句

??跳转语句有三种:break、continue、return。此外,异常处理也可以改变程序执行流程。
??break有以下作用:

  1. 在switch中,用来终止一个语句序列。
  2. 用来退出一个循环。

??continue只能用来for、while、do while循环中,用于跳过当前循环,直接进行下一次循环。
??return语句使程序控制返回到调用它的地方,也就是:

  1. 返回方法的返回值;
  2. 终止当前程序。

??示例:

public class SkipTest {
	public static void main(String[] args) {
		int result = sum(10);
		System.out.println("所求的数字之和是:"+result);
	}
	
	private static int sum(int num){
		int s = 0;
		for(int i=1;i<=num;i++){
			if(i==3)
				continue;
			System.out.println("i:"+i);
			s=s+i;
			if(i==(num-1))
				break;
		}
		return s;
	}
}

??测试结果:

i:1
i:2
i:4
i:5
i:6
i:7
i:8
i:9
所求的数字之和是:42

??这段代码是一个序列的数字之和,不过不需要+3,所以在i == 3时,使用continue,表示跳过此次循环,进入下一次循环。我们也不希望+10,所以在i == (num-1)时,使用了break,直接跳出循环。return的作用就是返回到调用该方法的地方,有返回值的话将返回值返回,无返回值的话则不用返回。

1.4 switch是否能作用在byte上,是否能作用在long上,是否能作用在String上?

??在JDK1.5以前,switch(expr)中,expr 只能是 byte、short、char、int。
??从JDK1.5开始,Java 中引入了枚举类型,expr也可以是enum类型。
??从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的

  • 为什么只支持上面几种?int、String 都可以,为什么不支持 long ?

原因就是 switch 对应的 JVM 字节码 lookupswitch、tableswitch 指令只支持 int 类型。 byte、char、short 类型在编译期默认提升为 int,并使用 int 类型的字节码指令。所以对这些类型使用 switch,其实跟 int 类型是一样的。

1.5 continue、break、和return的区别是什么?

??在循环结构中,当循环条件不满足或循环次数达到要求后,循环会正常结束。但是,有时候可能需要在循环的过程中,提前终止循环,这就是需要用到以下关键词:

  • 1、continue
    ??指挑出当前的这一次循环,继续下一次循环。
  • 2、break
    ??指跳出整个循环体,继续执行循环下面的语句。
  • 3、return
    ??指跳出所在方法,结束该方法的运行。return一般有两种用法:
  1. return;,直接使用return结束方法执行,用于没有返回值函数的方法;
  2. return value;,return一个特定值,用于有返回值函数的方法。

二、数组

??一个数组就代表在内存中开辟一段连续(意味着有序)、用来存储相同类型数据的空间,其特征如下:

  1. 数组名代表的是连续空间的首地址。
  2. 通过首地址可以依次访问数组所有元素,元素在数组中的位置叫做下标,从0开始。
  3. 数组长度一旦声明,不可改变不可追加。

2.1 声明数组

??数组的声明方式有两种,以int型数组举例:int[ ] array和int array[ ],一般用第一种方式。

2.2 创建数组

??数组的创建方式也有两种,以int型数组举例。

	int[ ] array = new int[10]

?该语句的意思是创建一个容量大小为10的int型数组,数组中默认值是0。也就是说,当数组元素未赋值时,数组元素的值为数组元素类型的默认值(此处是int型,所以默认值是0)。

	int[ ] array1 = {1,2,3,4,5,6};
	int[ ] array2 = new int[ ]{1,2,3,4,5,6};

?这两个语句的意思都是创建一个容量大小为6的int型数组,数组中的初始值为1,2,3,4,5,6。

2.3 遍历数组

??数组的遍历方式也有两种,以int型数组举例。

  • 1、for循环
    ?最常用的遍历方式,示例:
    for(int i=0;i<array.length;i++)
        System.out.println(array[i]+" ");
  • 2、foreach循环
    ?示例:
    for(int arr:array)
        System.out.println(arr+" ");

2.4 数组作为方法参数/方法返回值

??数组可以作为参数传递给方法。示例:

	//打印int数组中元素
	public static void printArray(int[] array) {
	  for (int i = 0; i < array.length; i++) {
	    System.out.print(array[i] + " ");
	  }
	}

??数组也可以数组作为函数的返回值。示例:

	public static int[] reverse(int[] list) {
	  int[] result = new int[list.length];
	 
	  for (int i = 0, j = result.length - 1; i < list.length; i++, j--) {
	    result[j] = list[i];
	  }
	  return result;
	}

2.5 数组复制

??对数组进行复制的方法,常常有System.arraycopy和使用Arrays工具类两种方法,这两种方法在JDK源码中经常出现。此处介绍第一种,具体的方法是:

	System.arraycopy(src, srcPos, dest, destPos, length)

?src: 源数组
?srcPos: 从源数组复制数据的起始位置
?dest: 目标数组
?destPos: 复制到目标数组的起始位置
?length: 复制的长度

??示例:

	static int[] arr1 = {1,2,3,4,5,6};
	static int[] arr2 = new int[6];
	
	public static void main(String[] args) {
		System.arraycopy(arr1, 0,arr2, 1, 3);
		for(int i=0;i<arr2.length;i++) {
			System.out.print(arr2[i] + " "); //0 1 2 3 0 0 
		}
	}

2.6 多维数组

??多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组,格式:

	type[][] typeName = new type[typeLength1][typeLength2];

??type 可以为基本数据类型和复合数据类型,typeLength1 和 typeLength2 必须为正整数,typeLength1 为行数,typeLength2 为列数。例如:

	int[][] a = new int[2][3];

??二维数组 a 可以看成一个两行三列的数组。
??给二维数组赋值的示例:

	String[][] s = new String[2][];
	s[0] = new String[2];
	s[1] = new String[3];
	s[0][0] = new String("Good");
	s[0][1] = new String("Luck");
	s[1][0] = new String("to");
	s[1][1] = new String("you");
	s[1][2] = new String("!");

三、String/StringBuffer和StringBuilder

??String(字符串),字符串是常量,它们的值在创建之后不能更改。这个特性可以从String的底层实现看出:

    //String的底层实现是字符数组
    private final char value[];

3.1 String的创建

??常常用来比较的两种创建字符串的方式:

	/*创建对象是在方法区的常量池*/
	String str1 = "one";
	/*创建对象是在堆内存*/
	String str2 = new String("one");

??第一种直接赋值的方式,创建的对象是在常量池;第二种通过构造方法,创建的对象是在堆内存
??JDK1.7 及之后版本的 JVM将运行时常量池从方法区中移了出来,在 Java 堆中开辟了一块区域存放运行时常量池。
??这两种变量的比较方式也有两种:

	System.out.println(str1==str2);    //false    
	System.out.println(str1.equals(str2));   //true

??==比较的是对象的地址,str1对象和str2对象分别在常量池(常量池一般就是指字符串常量池,是用来做字符串缓存的一种机制)和堆,所以用此方式比较的结果为false。equals比较的是对象的值,所以比较结果为true。

??在Object类中,equals()是用来比较内存地址的,但是String类中重写了equals()方法,用来比较内容。

??直接赋值创建字符串对象的方式,在创建多个相同内容的对象时,也只开辟一块内存空间,并且会自动入常量池,不会产生垃圾。通过构造方法创建字符串对象的方式,在创建多个相同内容的对象时,会开辟多个内存空间,并且创建的对象不在常量池里。因此,在实际开发过程中,都是使用直接赋值的方法创建字符串对象
??在字符串使用equals比较时,一般把要比较的对象放前面,避免出现空指针问题,示例:

	String str1 = "one";        
	System.out.println("two".equals(str1));

3.2 String常用方法

  • 1、获取指定位置字符
	public char charAt(int index)

??示例:

	String str1 = "abcdef";
	System.out.println(str1.charAt(1)); //b

??从上面可以看出使用charAt时,索引下标是从0开始的,这也从侧面说明了String的底层实现是数组。

  • 2、字符串比较
	public native int compareTo(String string)

??返回值是整型,它是先比较对应字符的大小(ASCII码顺序),如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值,如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方结束。示例:

	String str1 = "one";
	String str2 = "one";
	String str3 = "on1two";
	String str4 = "onetwo";
	System.out.println(str1.compareTo(str2));  //0
	System.out.println(str1.compareTo(str3));  //52
	System.out.println(str1.compareTo(str4));  //-3
	System.out.println(str3.compareTo(str4));  //-52
  • 3、字符串连接
	public String concat(String string)

??示例:

	String str1 = "abcdef";
	String str2 = "123";
	System.out.println(str1.concat(str2)); //abcdef123
  • 4、是否以指定子字符串开头
	public boolean startsWith(String prefix)

??示例:

	System.out.println("abcde".startsWith("ab")); //true
  • 5、判断字符串是否以指定的后缀结尾
	public boolean endsWith(String suffix) 

??示例:

	String str1 = "abcdef";
	String str2 = "123";
	String str3 = "def";
	System.out.println(str1.endsWith(str2)); //false
	System.out.println(str1.endsWith(str3)); //true
  • 6、比较两个字符串是否相等
	public boolean equals(Object other)

??此处重写了Object的euqals方法,String中重写equals方法的步骤:

  1. 使用==操作符检查“实参是否为指向对象的一个引用”。
  2. 使用instanceof操作符检查“实参是否为正确的类型”。
  3. 把实参转换到正确的类型。
  4. 对于该类中每一个“关键”域,检查实参中的域与当前对象中对应的域值是否匹配。
  • 7、忽略大小写进行比较
	public boolean equalsIgnoreCase(String string)

??示例:

	System.out.println("asd".equalsIgnoreCase("ASD")); //true
  • 8、从初始位置,检索字符第一次出现的位置
	public int indexOf(int c)

??示例:

	String str = "asd";
	System.out.println(str.indexOf('s')); //1
  • 9、从指定位置,检索字符第一次出现的位置
	public int indexOf(int c, int start)

??示例:

	String str = "asdfg";
	System.out.println(str.indexOf('s',2)); //-1,代表没检索到
	System.out.println(str.indexOf('s',0)); //1
  • 10、检索子字符串第一次出现的位置
	public int indexOf(String string)

??示例:

	System.out.println("abcde".indexOf("cd")); //2
  • 11、从指定位置,检索字符串第一次出现的位置
	public int indexOf(String subString, int start)

??示例:

	System.out.println("abcde".indexOf("cd",2)); //2
  • 12、从初始位置,检索字符最后一次出现的位置
	public int lastIndexOf(int c)

??示例:

	System.out.println("abcde".lastIndexOf('c')); //2
  • 13、从指定位置,检索字符最后一次出现的位置
	public int lastIndexOf(int c, int start)

??示例:

	System.out.println("abcde".lastIndexOf('c',3)); //2
  • 14、检索字符串最后一次出现的位置
	public int lastIndexOf(String string)

??示例:

	System.out.println("abcde".lastIndexOf("bc")); //1
  • 15、从指定位置,检索字符串最后一次出现的位置
	public int lastIndexOf(String subString, int start)

??示例:

	System.out.println("abcde".lastIndexOf("bc",2)); //1
  • 16、字符串长度
	public int length()

??示例:

	System.out.println("abcde".length()); //5
  • 17、按指定规则分割字符串
	public String[ ] split(String regularExpression)

??示例:

	String str = new String("Y-s-t-e-n");
    System.out.println("分隔符返回值 :" );
    for (String s: str.split("-")){
        System.out.println(s);
    }

??测试结果:

分隔符返回值 :
Y
s
t
e
n

??此处需要注意的是,使用split对字符串string进行分割字符串时,如果str中没有符合规则的,就返回完整的str字符串。示例:

	String str = new String("Y-s-t-e-n");
    System.out.println("分隔符返回值 :" );
    for (String s: str.split("2")){
        System.out.println(s);
    }

??结果:

分隔符返回值 :
Y-s-t-e-n

  • 18、截取子字符串,从指定位置到末尾
	public String substring(int start)

??示例:

	System.out.println("abcde".substring(1)); //bcde
  • 19、截取子字符串,从start(包含)到end(不包含),即区间是前开后闭
	public String substring(int start, int end)

??示例:

	System.out.println("abcde".substring(1,3)); //bc
  • 20、删除字符串的头尾空白符
	public String trim()

??示例:

	System.out.print(" asdfg ".trim());   //asdfg
  • 21、将不同类型的参数转化为字符串
	public static String valueOf(primitive data type x)

??示例:

	long l1 = 1001L;
	int i1 = 123;
	System.out.println(String.valueOf(l1));  //1001
	System.out.println(String.valueOf(i1));  //123
  • 22、将字符串转成小写字母
	public String toLowerCase()
  • 23、将字符串转成大写字母
	public String toUpperCase()

3.3 String拼接原理

??String:常量,不可变,不适合用来字符串拼接,每次都是新创建的对象,消耗较大;
??StringBuffer:适合用来作字符串拼接,线程安全
??StringBuilder:JDK1.5引入,适合用来作字符串拼接,与StringBuffer区别是线程不安全的。

??从上面也能看出,String拼接时,中间会产生StringBuilder对象(JDK1.5之前产生StringBuffer)。具体的原理是:

??两个字符串str1, str2拼接时,首先会调用 String.valueOf(obj)方法,这个obj为str1,然后产生StringBuilder, 调用的StringBuilder( )构造方法, 把StringBuilder初始化,长度为str1.length()+16,并且调用append(str1)。接下来调用StringBuilder.append(str2), 把第二个字符串拼接进去, 然后调用StringBuilder.toString()返回结果。

3.4 String相关问题

3.4.1 什么是字符串常量池?

??字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串。在创建字符串时,JVM会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。

3.4.2 String有哪些特性?

  • 1、不变性
    ??String 是只读字符串,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。
  • 2、常量池优化
    ??String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。
  • 3、final
    ??使用final来定义String类,表示String类不能被继承,提高了系统的安全性。String类利用了final修饰的char类型数组存储字符,源码:
	private final char value[];

3.4.3 为什么String在Java中是不可变的?

??String是Java中一个不可变的类,所以他一旦被实例化就无法被修改。不可变类的实例一旦创建,其成员变量的值就不能被修改。不可变类有很多优势。本文总结了为什么字符串被设计成不可变的。将涉及到内存、同步和数据结构相关的知识。

  • 1、字符串池
    ??字符串池(String intern pool)是方法区的特殊存储区域。创建字符串时,如果池中已存在该字符串时,将返回现有字符串的引用,而不是创建新对象。
  • 2、缓存Hashcode
    ??Java中经常会用到字符串的哈希码(hashcode)。例如,在HashMap或HashSet中,字符串的不可变能保证其hashcode保持一致,这样就可以避免一些不必要的麻烦。这也就意味着每次在使用一个字符串的 hashcode 的时候不用重新计算一次,这样更加高效。在String类中,有以下这段代码:
	/** Cache the hash code for the string */
	private int hash; // Default to 0

??此处的 hash 变量就是为了保存了String对象的hashcode,因为String类不可变,所以一旦对象被创建,该hash值也无法改变。所以,每次想要使用该对象的hashcode的时候,直接获取即可。

  • 3、易于在其他对象中使用
    ??示例:
	HashSet<String> set = new HashSet<String>();
	set.add(new String("a"));
	set.add(new String("b"));
	set.add(new String("c"));
	 
	for(String a: set)
		a.value = "a";

??如果字符串可以被改变,那么以上用法将有可能违反Set的设计原则,因为Set要求其中的元素不可以重复。上面的代码只是为了简单说明该问题,其实String类中并没有value这个字段值。

  • 4、安全性
    ??String被广泛的使用在其他Java类中充当参数。比如网络连接、打开文件等操作。如果字符串可变,那么类似操作可能导致安全问题。因为某个方法在调用连接操作的时候,他认为会连接到某台机器,但是实际上并没有(其他引用同一String对象的值修改会导致该连接中的字符串内容被修改)。可变的字符串也可能导致反射的安全问题,因为他的参数也是字符串。
    ??String 在其他 Java 类中被广泛作为参数使用,比如网络连接、打开文件等操作。如果字符串可变,那么类似这样的操作可能导致安全问题。比如,当某个方法在调用连接操作时,他会认为连接到了它已知的某台机器,但实际并没有。因为引用同一String对象的值被修改了。同时可变字符串也可能在Reflection中引起安全问题,因为参数是字符串。
    ??示例:
	boolean connect(string s){
	    if (!isSecure(s)) { 
			throw new SecurityException(); 
		}
	    //here will cause problem, if s is changed before this by using other references.    
	    causeProblem(s);
	}
  • 5、不可变对象自然是线程安全的
    ??由于无法更改不可变对象,因此可以在多个线程之间自由共享它们,不存在同步的问题。

??总之,String被设计成不可变的主要目的是为了安全和效率。

3.4.4 常量池的使用

?示例:

	String s1="a"+"b"+"c";
	String s2="abc";
	System.out.println(s1==s2);  //true
	System.out.println(s1.equals(s2));   //true

??创建s1对象时,就在常量池中产生了一个"abc"字符串,所以再用赋值的方式创建相同内容的字符串时,就直接使用常量池中,不再重复创建,所以两种比较方式的结果都是true,因为本就是一个对象。

3.4.5 常规字符串拼接

?示例:

	String s1="ab";
	String s2="abc";
	String s3=s1+"c";
	System.out.println(s3==s2);    //false     
	System.out.println(s3.equals(s2));   //true

??结果分析:s2是创建在常量池中的,s3是通过字符串拼接生成的,底层是通过StringBuilder(或 StringBuffer)对象实现的,这样产生的对象是存在堆内存中的。所以两者的地址是不一样的,==比较结果是false;内容是一样的,equals比较结果是true。

3.4.6 特殊字符串拼接

?示例:

	String s = null;  
	s += "abc";  
	System.out.println(s);  //nullabc
	s += null;
	System.out.println(s);  //nullabcnull

??结果分析:字符串拼接时,会先调用String.valueOf(Object obj)来将对象转换为字符串,该方法的实现是:

    public static String valueOf(Object value) {
        return value != null ? value.toString() : "null";
    }

??所以在字符串拼接时,会先判断是不是null,是null的话,会先转换成"null",而不是""进行拼接。
??字符串常量池是在编译期确定好的,一次性创建一个完整的字符串(String s1="zxc"或String s2=“z”+“xc”)时会去常量池查找
??字符串拼接(如:str+"asd")是在运行期确定的,不会去常量池查找。此时新的对象会分配到堆内存中,字符串拼接的实际过程:

	String s2 = new StringBuilder(str).append("asd").toString()

3.4.7 String s=new String(“abc”) 创建了几个对象?

??答案是一个或两个。new String()的形式无疑是会生成一个String对象的,接下来就看下String的构造方法:

	public String(String original)

??从上面代码可以看出,该构造方法中的参数也是一个String对象,相当于是:

	String str = "abc";
	String s=new String(str) ;

??这样来看这道题就容易理解了,当字符串常量池中有“abc”时,就不会产生新的相同内容的对象;反之会创建,所以该问题的答案是一个或两个。

3.4.8 equals与==的区别

??Java对于eqauls方法和hashCode方法是这样规定的:

  1. 如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
  2. 如果两个对象的hashCode相同,它们并不一定相同。

??在上面介绍的String类中,重写了equals方法,那么在日常开发中,怎么使用这两者呢?
??‘==’ 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作,比较规则有三:

  1. 比较的是操作符两端的操作数是否是同一个对象。
  2. 两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
  3. 比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。

??equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。
??总的来说,要进行比较时,参考有二:

  1. 自定义类中尽量重写equals方法。
  2. 在使用equals进行比较时,把常量写在前面,因为常量与变量比较时,变量可能为null,此时会出现空指针异常

3.4.9 String str="i"与 String str=new String(“i”)一样吗?

??不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中

3.4.10 在使用HashMap的时候,用String做key有什么好处?

??HashMap内部实现是通过key的hashcode来确定value的存储位置,因为字符串是不可变的,所以当创建字符串时,它的hashcode被缓存下来,不需要再次计算,所以相比于其他对象更快。

3.5 StringBuffer

??StringBuffer是可变字符序列,它是一个类似于String的字符串缓冲区,可以装很多字符串,并且能够对其中的字符串进行各种操作。
?? StringBuffer是线程安全的,因为其对外提供的方法都有synchronized关键字修饰。StringBuffer常见方法:

  • 1、构造方法
    public StringBuffer() {
    }
    public StringBuffer(String string) {
        super(string);
    }

??无参StringBuffer构造方法,默认开辟16个字符的长度的空间。

  • 2、追加字符串
	public synchronized StringBuffer append(String string)

??示例:

	String str = "abc";
	StringBuffer sb = new StringBuffer(str);
	System.out.println(sb.append("def"));  //abcdef
  • 3、插入字符串
	public synchronized StringBuffer insert(int index, String string)

??示例:

	String str = "abc";
	StringBuffer sb = new StringBuffer(str);
	System.out.println(sb.insert(3,"hhh"));  //abchhh
  • 4、转换为字符串
	public synchronized String toString()

3.6 StringBuilder

?? StringBuilder是JDK1.5提出来的。StringBuilder是可变字符序列,也是一个类似于String的字符串缓冲区,可以装很多字符串。并且能够对其中的字符串进行各种操作。
?? StringBuilder是线程不安全的。tringBuilder常见方法:

  • 1、构造方法
    public StringBuilder() {
    }
    public StringBuilder(String str) {
        super(str);
    }
  • 2、追加字符串
	public StringBuilder append(String str)

??示例:

	String str = "abc";
	StringBuilder sb = new StringBuilder(str);
	System.out.println(sb.append("qwe"));  //abcqwe
  • 3、插入字符串
	public StringBuilder insert(int offset, String str)

??示例:

	String str = "abc";
	StringBuilder sb = new StringBuilder(str);
	System.out.println(sb.insert(2, "qwe"));  //abqwec
  • 4、转换为字符串
	public String toString()

3.7 String、StringBuffer和StringBuilder的比较

??三者共同之处:都是final类,不允许被继承。

  • 三者不同之处
StringStringBufferStringBuilder说明
长度是否可变不可变可变可变StringBuffer和StringBuilder可以通过append等方法改变长度
运行速度较慢最快String最慢的原因:String为字符串常量;
StringBuilder和StringBuffer均为字符串变量,可更改
线程是否安全是(因为是字符串常量)线程安全线程不安全
适用情况适用于少量的字符串操作的情况多线程下在字符缓冲区进行大量操作的情况单线程下在字符缓冲区进行大量操作的情况实际上,StringBuffer的适用场景非常少,虽然它的线程安全,也仅仅是Jvm不抛出异常顺利往下执行,不能保证逻辑正确和调用顺序正确,大多数时候,需要的不仅仅是线程安全,而是锁

四、方法

??方法是语句的集合,它们在一起执行一个功能;方法是解决一类问题的步骤的有序组合;方法包含于类或对象中。
??方法的命名一般用驼峰命名法,即第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写。
??方法的优点:

  1. 使程序变得更简短而清晰。
  2. 有利于程序维护。
  3. 可以提高程序开发的效率。
  4. 提高了代码的重用性。

4.1 方法的定义

??一般情况下,定义一个方法包含以下语法:

修饰符 返回值类型 方法名(参数类型 参数名){
    ...
    方法体
    ...
    return 返回值;
}

??方法包含一个方法头和一个方法体。下面是一个方法的所有部分:

  • 修饰符
    ??修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
  • 返回值类型
    ??方法可能会返回值。returnValueType:方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
  • 方法名
    ??是方法的实际名称。方法名和参数表共同构成方法签名。
  • 参数类型
    ??参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
  • 方法体
    ??方法体包含具体的语句,定义该方法的功能。

4.2 变量作用域

??变量的范围是程序中该变量可以被引用的部分。
??方法内定义的变量被称为局部变量。局部变量的作用范围从声明开始,直到包含它的块结束。局部变量必须声明才可以使用。
??方法的参数范围涵盖整个方法。参数实际上是一个局部变量。
??最常见的局部变量是:for循环的初始化部分声明的变量,其作用范围在整个循环。但循环体内声明的变量其适用范围是从它声明到循环体结束。它包含如下所示的变量声明:

你可以在一个方法里,不同的非嵌套块中多次声明一个具有相同的名称局部变量,但你不能在嵌套块内两次声明局部变量。

五、常用类

5.1 Math类

??Math类包含用于执行基本数学运算的方法。最常用的方法是数值计算类方法。

  • 1、绝对值
	public static double abs(double d)
	public static float abs(float f)
	public static int abs(int i)
	public static long abs(long l)
  • 2、对一个数进行上舍入,返回值大于或等于给定的参数,类型为双精度浮点型
	public static native double ceil(double d)

??示例:

    double d = 10.6;
    float f = -95;   
    System.out.println(Math.ceil(d));   //11.0
    System.out.println(Math.ceil(f));    //-95.0
  • 3、对一个数进行下舍入,返回给定参数最大的整数,该整数小于或等给定的参数
	 public static native double floor(double d)

??示例:

        double d = 10.6;
        float f = -95;   
        System.out.println(Math.floor(d));   //10.0
        System.out.println(Math.floor(f));   //-95.0
  • 4、返回参数的自然数底数的对数值
	public static native double log(double d)

??示例:

    System.out.printf("log(%.3f) 为 %.3f%n", 
    	Math.E*Math.E,Math.log(Math.E*Math.E));  //log(7.389) 为 2.000
  • 5、返回double值的底数为10的对数
	public static native double log10(double d)

??示例:

	System.out.printf("log(%.3f) 为 %.3f%n", 
		100.0,Math.log10(100.0));   //log(100.000) 为 2.000
  • 6、返回较大值
	public static double max(double d1, double d2)
	public static float max(float f1, float f2)
	public static int max(int i1, int i2)
	public static long max(long l1, long l2)
  • 7、返回较小值
	public static double min(double d1, double d2)
	public static float min(float f1, float f2)
	public static int min(int i1, int i2)
	public static long min(long l1, long l2)
  • 8、返回第一个参数的第二个参数次幂的值
	public static native double pow(double x, double y)

??示例:

        double d1 = 10.0;
        double d2 = 2.0;   
        System.out.println(Math.pow(d1,d2));  //100.0
  • 9、返回一个随机数,随机数范围为 [0.0 ,1.0]
	public static synchronized double random()
  • 10、“四舍五入”,算法为Math.floor(x+0.5) ,即将原来的数字加上 0.5 后再向下取整
	public static long round(double d) / static int round(float f)

??示例:

    System.out.println(Math.round(11.5));    //12
    System.out.println(Math.round(-11.5));   //-11
  • 11、正平方根
	public static native double sqrt(double d)

5.2 Arrays类

?? Arrays是一个封装好一些对数组操作的类,其中的public方法都是静态的,主要有以下几大类:

  • 1、搜索类
    ?该类方法的作用是在数组中搜索某个值,返回该值在数组中的下标。该类方法的实现是二分搜索,例如在int数组中搜索某个值,方法实现代码:
    public static int binarySearch(int[] array, int startIndex, int endIndex, int value) {
        checkBinarySearchBounds(startIndex, endIndex, array.length);
        int lo = startIndex;
        int hi = endIndex - 1;

        while (lo <= hi) {
            int mid = (lo + hi) >>> 1;
            int midVal = array[mid];

            if (midVal < value) {
                lo = mid + 1;
            } else if (midVal > value) {
                hi = mid - 1;
            } else {
                return mid;  // value found
            }
        }
        return ~lo;  // value not present
    }
  • 2、赋值类
    ?该类方法的作用是给数组中元素赋予默认值,实现是遍历赋值。方法实现代码:
    public static void fill(int[] array, int start, int end, int value) {
        Arrays.checkStartAndEnd(array.length, start, end);
        for (int i = start; i < end; i++) {
            array[i] = value;
        }
    }
  • 3、计算哈希值类
    ?该类方法的作用是计算数组中元素的哈希值。方法实现代码:
    public static int hashCode(int[] array) {
        if (array == null) {
            return 0;
        }
        int hashCode = 1;
        for (int element : array) {
            // the hash code value for integer value is integer value itself
            hashCode = 31 * hashCode + element;
        }
        return hashCode;
    }
  • 4、比较值类
    ?该类方法的作用是比较两个数组是否相等。
  • 5、排序类
    ?该类方法的作用是对数组中的元素进行排序,用到的排序方式是快速排序。方法实现代码:
    public static void sort(int[] array, int start, int end) {
        DualPivotQuicksort.sort(array, start, end);
    }
  • 6、转换为字符串类
    ?即toString方法。
  • 7、拷贝类
    ?该类方法的作用是拷贝数组中的元素,可以指定起始位置,未指定初始位置的话,默认从0开始。方法实现代码:
    public static int[] copyOf(int[] original, int newLength) {
        if (newLength < 0) {
            throw new NegativeArraySizeException(Integer.toString(newLength));
        }
        return copyOfRange(original, 0, newLength);
    }
  • 8、转换为List
    ?asList,示例:
	int[] datas = {1,2,3,4,5,6};
	List list = Arrays.asList(datas);

5.3 Collections类

??Collections类是针对集合操作的工具类。

	public class Collections extends Object

??常用方法:

  • 1、排序,默认是自然排序(排序算法是修改的归并排序算法)
	public static void sort(List list)

??使用默认排序规则和自定义规则的示例:

        Collections.sort(list);
        Collections.sort(list,new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                if(o1.length()>o2.length()){
                    return 1;
                }else if(o1.length()<o2.length()){
                    return -1;
                }else{
                    return 0;
                }
            }
        });
  • 2、二分查找(前提元素有序)
	//二分查找的时候需要先进行排序操作,如果没有排序的话,是找不到指定元素的
	public static int binarySearch(List<?> list,T key) ? ?
  • 3、获取集合中最大值
	public static T max(Collection<?> coll)
  • 4、获取集合中最小值
	public static T min(Collection<?> coll)
  • 5、反转集合
	public static void reverse(List<?> list)

5.4 Object类

5.4.1 Object常用方法

??Object是是所有类的父类,如果一个类没有用extends明确指出继承于某个类,那么它默认继承Object类。JDK1.8版本中,Object类中的一些方法:

  • 1、构造方法
    ??Object类中没有显示的提供构造方法,由编译器默认提供。
  • 2、getClass
	public final native Class<?> getClass();

??此方法返回类运行时的类型,示例:

	public class JavaTest {
		public static void main(String[] args)  {
			//class com.test.JavaTest
			System.out.println((new JavaTest()).getClass());  
		}
	}
  • 3、hashCode
	public native int hashCode();

??示例:

	public class JavaTest {
		public static void main(String[] args)  {
			System.out.println((new JavaTest()).hashCode());  //2018699554
		}
	}

??该方法返回对象的哈希码,是一个整数。这个方法遵守以下三个规则:

  • 1、在java程序运行期间,若用于equals方法的信息或者数据没有修改,同一个对象多次调用此方法,返回的哈希码是相同的。
  • 2、如果根据equals方法,两个对象相同,则这两个对象的哈希码一定相同。
  • 3、假如两个对象通过equals方法比较不相同,那么这两个对象调用hashCode也不是要一定不同,相同也是可以的。

??在实际使用中,要尽量保证对于不同的对象产生不同的哈希码。hashCode的典型实现是将对象的内部地址转为一个整数,但是这种实现技术不是Java语言必须要采用的。

  • 4、equals
    public boolean equals(Object obj) {
        return (this == obj);
    }

??equals方法主要是比较两个对象是否相同,Object中的equals方法比较的是对象的地址是否相同。
??在实际开发中,对于实体类,一般要重写equals(比较对象的内容而不是地址)和hashCode(尽量让不同的对象产生不同的哈希值)方法。

  • 5、clone
	protected native Object clone() throws CloneNotSupportedException;

??浅拷贝一个对象。

  • 6、toString
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

??示例:

public class JavaTest {
	public static void main(String[] args)  {
		com.test.JavaTest@7852e922
		System.out.println((new JavaTest()).toString());  
	}
}

??可以看到Object中toString方法的实现是返回类的名称(全路径名称)加上@,然后加上此类的哈希码的16进制表示。

  • 7、wait
    ??在Object中存在三种wait方法:
	public final native void wait(long timeout) throws InterruptedException;
	public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }
    public final void wait() throws InterruptedException {
        wait(0);
    }

??wait()和wait(long timeout, int nanos)都在在内部调用了wait(long timeout)方法。这个方法是线程方面的,在线程相关文章会详细介绍。

  • 8、notify/notifyAll
	public final native void notify();
	public final native void notifyAll();

??这两个方法是唤醒线程,也会在后续线程相关文章中详细介绍。

5.4.2 hashCode与equals 【重要】

??hashCode() 的作用是获取哈希码(散列码);它实际上是返回一个int型整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。
??散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)
??hashCode()与equals()的相关规定:

1、如果两个对象相等,则hashcode一定也是相同的;
2、两个对象相等,对两个对象分别调用equals方法都返回true;
3、两个对象有相同的hashcode值,它们也不一定是相等的。

??因此,equals方法被覆盖过,则hashCode方法也必须被覆盖

  • Java中的hashCode()的作用
    ??hashCode()的作用是为了提高在散列结构存储中查找的效率,在线性表中没有作用;只有每个对象的 hash 码尽可能不同才能保证散列的存取性能,事实上Object 类提供的默认实现确实保证每个对象的 hash 码不同(在对象的内存地址基础上经过特定算法返回一个 hash 码)。
    ??在 Java 有些集合类(HashSet)中要想保证元素不重复可以在每增加一个元素就通过对象的 equals 方法比较一次,那么当元素很多时后添加到集合中的元素比较的次数就非常多了,也就是说如果集合中现在已经有 3000 个元素则第 3001 个元素加入集合时就要调用 3000 次 equals 方法,这显然会大大降低效率,于是 Java 采用了哈希表的原理,这样当集合要添加新的元素时会先调用这个元素的 hashCode 方法就一下子能定位到它应该放置的物理位置上(实际可能并不是),如果这个位置上没有元素则它就可以直接存储在这个位置上而不用再进行任何比较了,如果这个位置上已经有元素了则就调用它的 equals 方法与新元素进行比较,相同的话就不存,不相同就散列其它的地址,这样一来实际调用 equals 方法的次数就大大降低了,几乎只需要一两次,而 hashCode 的值对于每个对象实例来说是一个固定值。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:09:58  更:2022-03-30 18:10:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:04:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码