JAVA工程师——基础知识朝花夕拾

301 阅读27分钟

1.Switch- case

switch(表达式) 

 { case 常量表达式1:语句1;

 .... case 常量表达式2:语句2;

 default:语句; } 

 1、表达式值可以是 byte、short、int、char 从javaSE7之后可以使用String(编译时使用字符串hash值实现)

 2、case后语句可以不用大括号 

3、如果匹配到case,name会顺序执行之后的语句(包括default也按顺序执行),直到遇到break ———————————————— 版权声明:本文为CSDN博主「三朵耳朵」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_37499840/article/details/90075661

2.内存单位:

位=bit=binary digit ==八分之一字节(byte)=十六分之一字(代表一个汉字)


3. 变量

  •  引用变量
  •  基本数据类型
        3类 8种 基本数据类型 基本数据类型 (逻辑-boolean  ;文本型 -char ;数值型 -byte            、short、int 、long,float 、double) 

        Byte类型( 1 byte)、 short(2 byte)、 int (4byte)、 float             (4    byte)、 long(8byte) double (8byte),

        字符型( 2 Byte)

        整数型;默认 int ,浮点型,默认 double

 



或分为:

  • 成员变量(作用域比局部变量大),可以不用初始化。其中Static 修饰的是静态变量,普通的就是成员变量。静态变量。多个实例共享一份变量,可用类名进行引用。注意: 类的静态变量在内存中只有一个,java虚拟机在加载类的过程中为静态变量分配内存,静态变量位于方法区,被类的所有实例共享。静态变量可以直接通过类名进行访问,其生命周期取决于类的生命周期。而实例变量取决于类的实例。每创建一个实例,java虚拟机就会为实例变量分配一次内存,实例变量位于堆区中,其生命周期取决于实例的生命周期。
       注意点:1.JAVA中初始化的顺序:
      加载类;
     静态变量初始化;
     静态块;【其只能调度静态的,不能调度非静态的】
     成员变量;
      构造方法; 

      

静态成员变量的详解:https://www.cnblogs.com/liuguoguo/p/8525220.html

  • 局部变量,必须要初始化。

类型转化问题:

  • 高精度——>低精度转化需要强制类型转换,如果不写的话会强制报错的
  • 低精度——>高精度 自动完成
  • 如果高精度->低精度,右边的是常数(高精度),判断该常数范围是不是在小精度的范围里面,这样就可以自动提升 eg: byte b=3; 反例如果byte b=b+3,就会报错,因为不清楚b的取值范围
  • int 和 float做运算,结果是 float
  • char可以和整形相互转换,做运算,,相当于char的底层还是数字,用编码表将他转换显示出来。'a'+1  打印结果是98,如果需要字符,再强制转换
强制转化,类型需要加上括号( char)(num-9+'a')

4. 运算符

|和|| 右边这个会短路。左边判断完了,如果为真就不判断右边了

? 下图的符号运算优先级有点头皮发麻


判断表达式? A(表达式) :B(表达式); 可以赋值给一个变量

true ^ true = false; 

true ^ false = true;

 false ^ true = true; 

false ^ false = false; 

^异或的运算规律: ^符号的两边结果如果相同,结果是false, 两边的结果不同,结果是true。 

5. 进制

    以2进制为基准,1个bit为单位为2进制,3bit为单位是 8进制,生活场景使用的是十进制,4bit为基准为16进制。进制之间的转换以2进制为桥梁(如十进制90转成-0101-1010转化为16

进制,每三个bit变成十进制,然后连起来就可以)


负数表现形式:原数取反+1


移位:

往左移X,<<,其实启动过程像是往右边移动,乘以2的X倍

往右移X,<<,其实启动过程像是往左边移动,除以2的X倍 (往前面补齐位数的时候,补的是原有数据的最高位置(0/1)来补充)

<<< 无论最高位是什么,都用0来补

&:有假为假,

|: 有真为真

^ 异或:两边相同为假,反之为真

一个数异或一个数两次,结果还是那个数

可以用异或,从2进制转换为16进制:首先异或15(与1111(十进制中的15进行异或,得到末尾4位的位1的值;利用左移功能循环取其他剩下的位当中位1的值))

6 循环

for 和 while

for中的循环标记量是局部变量

while中的循环标记量是全局变量

W: for()  W:表示给循环起名字,

break 只是跳出最内层循环(不循环了,continue停止本次,break停止所有的循环),如果 break W, 表示跳出标号为W的循环(break可用于循环和switch)

continue 也可以使用循环标号

注意: 增强for循环格式:for(变量类型 变量名:被遍历的数组)



7.数组和内存







方法:开辟的空间是在stack内存里面,其中的局部变量也在里面,当函数执行完毕这部分内存就会消失。数据使用完,空间自动释放。(局部变量都在栈内存里面)

实体(包括数组和对象):都在堆里,new出来的东西都放在堆里。




堆内存三个特点:

  1. 垃圾自动回收
  2. 内存地址值
  3. 自动初始化
栈内存:

自动释放

内存的分类:

1.栈2. 堆3.方法区4.


栈空间的a赋值给b(基本数据类型,没有指向地址),则值复制一份给b,a的值不变,改变b的值,a也没发生改变

冒泡排序:相邻两个元素进行比较,换位置,这样最右边的就是最值了。经过多次之后顺序就排完了

选择排序:每一轮数组的首个元素和剩下的不断比较

Arrays.sort();//利用模块中现成的方法排序

折半查找:


8. 面向对象:

匿名对象:new Car().run();

  1. 当对象对方法仅进行一次调用的时候,就可以简化成匿名对象。 
  2. 匿名对象可以作为实际参数进行传递
       public static void show(Car c)

private: 修饰成员,权限只在本类里面可以获取

構造方法:可以有修饰符,没有返回值。


静态代码块:和函数代码块同一级别

随着类的加载而执行。而且只执行一次。 作用: 用于给类进行初始化

static

 num = 10; // num *=3; 

 System.out.println("hahahah");

 } 



构造代码块。可以给所有对象进行初始化的。与函数同一级别

System.out.println("constructor code ");

 // cry();

}   


 1,局部代码快。 对局部变量的生命周期进行控制。如if语句框

 2,构造代码块。 对所有对象进行初始化。 

 3,静态代码块。 对类进行初始化。


static 静态关键字用法详解:

1,static是一个修饰符,用于修饰成员

2.static修饰的成员被所有的对象所共享。 

3,static优先于对象存在,因为static的成员随着类的加载就已经存在了。 

4,static修饰的成员多了一种调用方式,就可以直接被类名所调用 。 类名.静态成员 。

5,static修饰的数据是共享数据,对象中的存储的是特有数据。

 

成员变量和静态变量的区别? 

1,两个变量的生命周期不同。 成员变量随着对象的创建而存在,随着对象的被回收而释放。 静态变量随着类的加载而存在,随着类的消失而消失。

 2,调用方式不同。 成员变量只能被对象调用。 静态变量可以被对象调用,还可以被类名调用。

 3,别名不同。 成员变量也称为实例变量。 静态变量称为类变量。

 4,数据存储位置不同。 成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据. 静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据. 

 静态使用的注意事项: 

1,静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态) 

2,静态方法中不可以使用this或者super关键字。 

3,主函数是静态的


this 关键字的用法:

1.this可以区分成员变量与局部变量

 class Person

 { 

 private String name; 

 private int age; 

 Person(String name) 

 { 

 //成员变量和局部变量重名,可以用关键字this区分

 this.name = name; 

 }

 public void speak() 

 { 

 //输出时,会默认为成员增加this关键字,用来代表具体对象的数据 System.out.println(this.name+":"+this.age);

 } 

 }


2.this也可以用于在构造函数中调用其他构造函数。

3.this 指代调用函数的当前


类有默认的不带参数的构造函数,如果显示的写了带参数的构造函数,则这个不带参数的会被覆盖,此时若再调用无参数的构造函数,则会报错。

构造函数没有 具体的返回值。但是,没有 具体的返回值。但是,没有 具体的返回值。但是,没有 具体的返回值。但是,没有 具体的返回值。但是,没有 具体的返回值。但是,没有 具体的返回值。但是returnreturn return return语句,用于结束构造函数。 语句,用于结束构造函数。 语句,用于结束构造函数。 语句,用于结束构造函数。 语句,用于结束构造函数。 语句,用于结束构造函数。 语


9 继承

假设classB extends classA , 子类的所有构造函数(包括无参构造函数,有参构造函数),如果不是显式调用哪种超类构造函数,都会默认调用super(),即:父类的无参构造函数,如果此时父类中没有无参构造函数的话,报错~ 建议父类也添加一个无参构造函数 。

注:子类自定义有参数的构造函数的时候,需要写个super(且保证能够对应的上父类的构造函数,如果super没有带参数,则父类需要有无参数的构造函数,如果没有,则需要在super()加上目前有的父类的参数);不显示的构造函数会自动调用super()。

在深度继承关系中,即当存在C继承B,B继承A,或者更多层继承时,首先执行最上层的构造函数,再依次顺着继承链传递下去,一直到 创建对象的那个类。例如:我们声明C对象时,调用的是C的构造函数c,构造函数c调用的是父类B的构造函数b,构造函数b调用

的是父类A中的构造函数a,那么执行结果就是:a => b => c 


继承&构造凼数:

 /* 子父类中的构造函数的特点。 在子类构造对象时,发现,访问子类构造函数时,父类也运行了。 为什么呢? 原因是:在子类的构造函数中第一行有一个默认的隐式语句。 super(); 子类的实例化过程:子类中所有的构造函数默认都会访问父类中的空参数的构造函数。 

 为什么子类实例化的时候要访问父类中的构造函数呢? 那是因为子类继承了父类,获取到了父类中内容(属性),所以在使用父类内容之前, 要先看父类是如何对自己的内容进行初始化的。 所以子类在构造对象时,必须访问父类中的构造函数。 为什么完成这个必须的动作,就在子类的构造函数中加入了super()语句。 

 如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用 父类中哪个构造函数。同时子类构造函数中如果使用this调用了本类构造函数时, 那么super就没有了,因为super和this都只能定义第一行。所以只能有一个。 但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。 注意:supre语句必须要定义在子类构造函数的第一行。因为父类的初始化动作要先完成。 */   




单例模式:

1.饿汉式,类一加载,对象就存在。使用private 静态类变量创建一个对象,然后通过一个公有静态函数将他返回出来。

2.懒汉式,只有调用函数的时候,对象才能够生成,在调用函数的时候,需要判断该私有类变量(static)是否存在该类的对象,如果没有,才调用私有构造方法进行创建,最后将类变量实例传出去。

单例模式在内存中的体现:

首先涉及到三个区域:1.heap2.stack3.方法区

静态成员,静态成员的引用在stack里面,创建的对象是在在堆内存里面。

如图所示:




10. 抽象类

  • 抽象类可以不包含抽象方法,,包含抽象方法的类一定是抽象类。
  • 抽象类中有构造函数 ,用于给子类对象进行初始化。
  • 方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。 抽象方法必须定义在抽象类中。该类必须也被abstract修饰。  
  • 抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化。 否则,这个子类还是抽象类。 

抽象关键字不可以和那些关键字共存? 

private 不行(其实暗含着final的意思)

static 不行

final 不行 


final关键字: 

1,final是一个修饰符,可以修饰类,方法,变量。 

2,final修饰的类不可以被继承。 

3,final修饰的方法不可以被覆盖。 

4,final修饰的变量是一个常量,只能赋值一次。 为什么要用final修饰变量。其实在程序如果一个数据是固定的, 那么直接使用这个数据就可以了,但是这样阅读性差,所以它该数据起个名称。 而且这个变量名称的值不能变化,所以加上final固定。


11.接口(interface)

  1. 类与类之间是继承关系,类与接口直接是实现关系。 
  2.  接口不可以实例化。 只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。 否则,这个子类就是一个抽象类。
  3. 接口中的成员都是公共的权限
  4. 当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用 另一种形式定义和表示,就是接口 interface。(接口里面不能有非抽象方法) 
  5. 接口的出现避免了单继承的局限性
  6. 接口可以继承接口,多继承接口也可。类可以多实现多个接口
interface CC { void show(); } 

interface MM { void method(); }

 interface QQ extends CC,MM//接口与接口之间是继承关系,而且接口可以多继承。

 { 

 void function(); 

}

 class WW implements QQ

 {

 //覆盖3个方法。

 public void show(){} public void method(){} public void function(){}

 }


接口和抽象类异同点: 

 相同点: 都是不断向上抽取而来的。 

 不同点: 

 1,抽象类需要被继承,而且只能单继承。 接口需要被实现,而且可以多实现。 

 2,抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。 接口中只能定义抽象方法,必须由子类去实现。

 3,抽象类的继承,是is a关系,在定义该体系的基本共性内容。 接口的实现是 like a 关系,在定义体系额外功能


12. 多态

关键字:instanceof,用于判断对象的具体类型。只能用于引用数据类型判断

a instanceof Cat

体现:父类或者接口的引用指向其子类的对象;

Animal a=new Cat(); 

a.eat()调用的是子类的eat()//根据函数的复写特点


多态的成员变量的特点:

1.对于成员方法,在多态中,父类引用指向子类对象,编译的时候,看的是父类是否包含这几个方法;运行的时候,子类和父类都有的方法,运行子类的复写的方法;如果子类没有改写,就调用从父类继承来的函数

2.对于成员变量,在多态中,父类引用指向子类对象,编译和运行的时候,都看的是父类的(假如父类和子类都有num对象)

如果父类有空参数的构造方法,则子父类的构造函数同一个参数进行参数共享。(不是像之前一样只看父类了)

在多态中,子类父类名字参数一样,返回值不一样,这样不能重载也不能重写,因此会编译失败。



3.对于静态函数和成员,编译和运行结果都参考左边


动态绑定和静态绑定


多态转型:

1.向上转型,类比于基本数据类型,精度自动提升,从小范围,到大范围

Animal a=new Cat(); 

只能调用父类中有的成员,结果是子类重载的结果,如果调用了子类的特有方法会报错。

2.向下类型转换

Cat c=(Cat)a 

不能未卜先知。先要有多态关系。

此时可以调用子类特有方法

多态自始自中都是对象在发生改变

毕老师 和毕姥爷的例子


多态的前提:

1.类之间实现了继承或者实现

2.方法之间存在覆盖


多态的弊端:

只能预先用父类的引用访问父类中的成员。

目的:

1.增加了代码的复用性



11.Object 类

equals()方法,比较对象时,比较地址是否相同,等价于==

对equals()需要修改他的比较方式:

1.在待使用的类里面重写 compare()方法

2.重写 equals方法,注意(1.用多态向下转型用子类当中的成员变量,在此例子中,Object没有num属性2.注意判断 是不是相同的类之间比较)

toString()方法一般需要重写;


13 内部类:

1.作用:避免多生成一些不必要的对象,为了使用对象里面的某些值

2.用法:

  1.        内部内可以直接访问外部类的成员变量,不用生成对象。eg:孙悟空进入牛魔王体           内, 原因,内部类中持有外部类的引用Outer.this(自动有的);
  2.       外部类访问内部类需要生成内部类的对象。
  3.        访问内部类可以:Outer.Inner (类型)xx=new Outer(). new Inner( ) (类型);
  4.        定位和成员变量差不多,可以用private等修饰符修饰,其实还可以放在局部
  5.        用处:当描述事物里面还有事物,并且内部这个还访问外部的资源
  6.        局部不能被static修饰?????? 局部内部内不能定义静态成员


内部类定义在局部的时候:

1.任然可访问成员变量

2.不可以被成员修饰符所修饰

3.不能访问它所存在的局部的变量,除了访问里面带有final修饰符的

4. 



匿名内部类:


記住匿名内部類調用完函數之後需要加上分號,如果是匿名内部類的最先開始定義,則記住不要加分號;



14. 异常类


非运行时异常,提示可能会出错,但是不一定出错,这样的情况他提示错误,最好用,try  catch 语句块进行 处理一下


有的异常结果,我们没有权限处理,不能用 try catch

这时可以用 throws进行处理://仅仅是抛给调用者,谁调用,谁处理,甩锅

定义方法  方法名字  throws  异常类名

{

}




运行时异常也可以用 try catch 和 throws方法进行处理,但是处理意义并不是很大,还得回去修改代码

自定义异常:

继承Exception类, 方法体内throw 一个异常,方法定义上需要throws 一个异常出去,告诉别人这里可能会出异常。

继承Runtime Exception :方法体上可以不用 throws 抛出,如果有问题JVM会自动抛出

补充,try catch 语句块,try里面出错的话,从错误的地方就不执行了,就去找catch语句块对应的类型,finally一定可以执行到的。


异常处理的原则: 

1,函数内容如果抛出需要检测的异常,那么函数上必须要声明(Throws)。 否则必须在函数内用trycatch捕捉,否则编译失败。

 2,如果调用到了声明异常的函数,要么trycatch要么throws,否则编译失败。

 3,什么时候catch,什么时候throws 呢? 功能内容可以解决,用catch。 解决不了,用throws告诉调用者,由调用者解决 。  

     说明:如果该功能内部可以将问题处理,用 try,如果处理不了,交由调用者处理,这是用 throws         区别: 当前程序需要继续运行就 try 当前程序不需要继续运行就throws 

     举例: 感冒了就自己       吃点药就好了,try 吃了好几天药都没好,结果得了 H7N9,那就得           throws到医院去对人进行       治疗 如果医院没有特效药,就变成 Error 了

 4,一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理。 内部又几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。catch里面的代码出错了之后会全部执行完。

子类覆盖父类只能抛出父类的异常或者子类或者子集。 注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try 



因为 什么自定义的结果都没输出,直接就抛异常了

另外一个13题,标识了异常。但是不一定出异常,结果又可能执行到,所以是能够编译。

内心OS(难道Try里面不可能输出自定义内容就会编译失败吗毕向东125Video)

throw break,return下面不要定义语句,因为执行不到


try或者

catch里面有return,也有finally,先把try,catch里面的东西执行完,再去执行finally里面的东西,执行完了之后执行之前的return,try catch finally体系后面的代码不执行了


多线程:

开启方式

1 创建Thread的子类,再把自定义代码放在run里面。start创建并启动线程(run的话不能直接启动线程,只能像调用函数一样调用)


2. 实现Runable 接口,重写run()方法,创建Thread 对象

创建线程的第一种方式:继承Thread类。 创建线程的第二种方式:实现Runnable接口。

 1,定义类实现Runnable接口。

 2,覆盖接口中的run方法,将线程的任务代码封装到run方法中。

 3,通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。 为什么?因为线程的任务都封装在Runnable接口子类对象的run方法中。 所以要在线程对象创建时就必须明确要运行的任务。

 4,调用线程对象的start方法开启线程。

 实现Runnable接口的好处:

 1,将线程的任务从线程的子类中分离出来,进行了单独的封装。 按照面向对象的思想将任务的封装成对象。

 2,避免了java单继承的局限性。 所以,创建线程的第二种方式较为常用。


线程的五大状态:



局部变量在每一个线程里面都会有一个独立的变量,互相不冲突


线程取名  

1.super()构造函数

获取线程名字:

1静态方法。currentThread()

2.this

线程改名字

类.setName()


同一个线程对象不能多次Start(),否则线程会蒙


多线程的安全问题:

1.当在循环里面写上一个sleep,循环,对于成员变量,多线程分享同一份。局部变量每个线程各有各的。这样到sleep之后的代码会产生滞后性,因此可能会造成安全问题。

解决方法用同步代码块

synchronized(任意一个·对象 )

{

放需要处理共享数据的语句

}

原理:obj相当于一个锁(有当前进程,标志位就是0,别的进程就进不来,出来之后就变成1的标志位)

火车上的卫生间例子。

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

同步的弊端:相对降低了效率,因为同步外的线程的都会判断同步锁。 

同步的前提:同步中必须有多个线程并使用同一个锁


同步可以作为修饰符,修饰函数,synchronized。作为修饰符。其中修饰函数的话,锁是this.

synchronized 放在run()上面,实际上只有一个线程正在运行。

函数被静态修饰,他的锁是Class类对象。字节码对象

类名.Class 该对象的类型是CLass

锁是针对当前线程来说的。嵌套锁的话容易造成死锁


线程之间的通信:

notify是唤醒等待时间最长的线程  wait()默认的锁是this. 使用在同步中


如果线程多了,需要操作同一个对象的不同方法,如果有不同步问题,可以采用notifyAall()和while(flag)循环判断问题。

对于生产者消费者的替代解决方法:


jdk1.5以后将同步和锁封装成了对象。 并将操作锁的隐式方式定义到了该对象中, 将隐式动作变成了显示动作。 Lock接口: 出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作。 同时更为灵活。可以一个锁上加上多组监视器。 lock():获取锁。 unlock():释放锁,通常需要定义finally代码块中。 Condition接口:出现替代了Object中的wait notify notifyAll方法。 将这些监视器方法单独进行了封装,变成Condition监视器对象。 可以任意锁进行组合。


守护线程:也叫做后台线程,依赖于正常线程而存在,在线程启动前进行设置。如果线程全部是守护线程,则JVM会退出。

 thread.setDaemon(true);


停止线程:

1.run方法的停止

      特殊情况:1.停止run当中的循环,用状态标记变量进行停止(可采用设置一个方法控制该标记)

                       2.线程wait了,不可用notify去通知,因为当前的线程已经冻结了,得用外部的力(interrupt方法进行强制引起Exception异常,接着可以在catch里面改变状态值了)

yield方法。使得该线程对象暂时交出执行权,有利于线程之间的平衡性能。

多线程的使用场景:当代码之间需要独立运行互不相关的时候,可以用多线程,其中有个小tips。可以在类里面使用Runnable接口和Thread子类的匿名内部类创建多线程。毕向东第154集。


String 类

字符串是特殊的类

两种创建方法

1. String a="abc"

2String a=new String("abc")  


特点:1.创建了之后就不会改变。

String a="abc"

a="kk"

打印a的话,啊

因为是类变量,他的指向变了,但是abc是不会变的

String s = "abc";//创建一个字符串对象在常量池中。

String s1 = new String("abc");//创建两个对象一个new一个字符串对象在堆内存中。 System.out.println(s==s1);//false System.out.println(s.equals(s1)); 

//string类中的equals复写Object中的equals建立了string类自己的判断字符串对象是否相同 的依据。 

//其实就是比较字符串内容。


String s1 = "abc";//创建一个字符串对象在常量池中。

 String s2 = new String("abc");//创建两个对象一个new一个字符串对象在堆内存中。

String s3="abc"

 System.out.println(s1==s2);//false 

 System.out.println(s1==s3);//true。因为abc是放在常量池里面的,对象都是一样的,所以就不用开辟新的空间了。所以s1==s3

其中 注意==表示 对象是否相同的比较

常量池在内存中是在方法区域里面。

方法区包括:1.静态区域2.方法3.常量池


字符串中,String a="abc",相当于是把abc 分别放入内存当中的常量池里面去。

String类的常见方法:

spilt(参数是用来分割的模板符号)

如 "a-b-v".spilt(-)就根据-来分割字符串。

将其他类型的数据转换为String,valueOf()


StringBuffer:就是字符串缓冲区。 * 用于存储数据的容器。 

* 特点:

 * 1,长度的可变的。 

* 2,可以存储不同类型数据。

 * 3,最终要转成字符串进行使用。

 * 4,可以对字符串进行修改。(修改之后,对象还是原对象(==的话会是true))


/* * jdk1.5以后出现了功能和StringBuffer一模一样的对象。就是StringBuilder * * 不同的是: * StringBuffer是线程同步的。通常用于多线程。 

* StringBuilder是线程不同步的。通常用于单线程。 它的出现提高效率。


包装类:

基本类型--->字符串 * 

1,基本类型数值+"" * 

2,用String类中的静态方法valueOf(基本类型数值); 

* 3,用Integer的静态方法valueOf(基本类型数值);


 * * 字符串--->基本类型 * 

1,使用包装类中的静态方法 xxx parseXxx("xxx类型的字符串");***** * int parseInt("intstring"); * long parseLong("longstring"); * boolean parseBoolean("booleanstring"); *

 只有Character没有parse方法 * 

2,如果字符串被Integer进行对象的封装。 

* 可使用另一个非静态的方法,intValue(); * 将一个Integer对象转成基本数据类型值。

3.Integer有构造函数,将string可以搞成包装类,再通过包装类型转换。


注意:

Integer i1=new Integer("123")

Integer i2=new Integer(123)

i1和i2的==是false,两个对象

            equals()已经被重写了,所以是内容一样,true


对于另一种情况:(以byte来衡量是否需要创建新的对象)

  Integer a = new Integer(128); Integer b = new Integer(128); System.out.println(a==b);//false

 System.out.println(a.equals(b));//true

 Integer x = 129;//jdk1.5以后,自动装箱,如果装箱的是一个字节,那么该数据会被共享不会 //重新开辟空间。 

 Integer y = 129; System.out.println(x==y);//false 

 System.out.println(x.equals(y));//true