基础语法
标识符:自己可以起名字的都叫做标识符。
规则:字母、下划线、数字、美元符组成,数字不能开头。
Java标识符大小写敏感,长度无限制
注:“见名知意”,不能乱起名字。
关键字:Java中所有关键字都是小写。
常量
整型常量:123 字符常量:'a' 实型常量:12.3 逻辑常量:true false 字符串常量:"helloworld"
变量
变量是内存中的一小块区域,使用变量名来访问区域,每一次变量使用前必须要先声明(申请),再进行赋值
变量的分类
局部变量:在方法体里,包括方法的参数。
成员变量:在方法体外,类体内。
注:在大括号{}里面出现的变量,除了大括号就无"人"认识。
Java数据类型
整数类型:整型常量默认int型,long类型可在数字后面加L
|
整数类型
|
字节数
|
范围
|
|
byte
|
1
|
-128~127
|
|
short
|
2
|
-2E15~2E15-1
|
|
int
|
4
|
-2E31~2E31-1
|
|
long
|
8
|
-2E63~2E63-1
|
浮点类型
Java浮点默认位double类型,若声明一个常数位float类型,需要在数字后加F
|
float
|
4字节
|
|
double
|
8字节
|
文件名与public class后的名称要一致
布尔型
boolean适用于逻辑运算,一般用于程序流程控制
boolean只允许取值true或false
char类型 单引号括起来的单个字符 例如:'\n'换行 '\r'回车
基本数据类型的转换
1、boolean类型不可以转换为其他的数据类型
2、整型,字符号,浮点型的数据在混合运算中相互转换
3、容量小的数据类型自动转化为容量大的 如 byte char short 自动转化为int
4、容量大的向容量小的转换要加上强制转换符,即在一个数据前写另一个数据类型进行强制转换。会降低精度。
5、有多种类型的数据混合运算时,系统首先自动的将所有数据转换成容量最大的那一种数据类型,再进行计算。
程序格式(有时比算法更重要)
1、大括号对齐 2、遇到{ 缩进 Tab 3、程序块之间加空行 4、并排语句之间加空格
5、运算符两侧加空格(注:for循环不用,因为已经有了很多空格) 6 { 前有空格 7、成对编程
核心要义:让别人看的清楚、舒服
Java运算符
算术运算符:+ - * / ++ -- 注:++(--)在前时,先运算再赋值;在后时,先赋值再运算
关系运算符:> < == >= <= !=
逻辑运算符:!(取反) &(与) |(或) ^(异或) &&(短路与) ||(短路或)
赋值运算符:= 当“=”两侧数据类型不一致时,可以适用默认类型转换或强制转换
输出结果 print(ln)有ln换行,无ln不换行、
“+”运算符两侧的操作数中只要有一个是字符串(String),系统会自动将另一个操作数转换为字符串然后再进行连接
循环
for(表达式1;表达式2;表达式3){语句 ; ... ; }
执行过程:首先计算表达式1,接着执行表达式2,若表达式2的值=true,则执行语句,接着计算表达式3,再判断表达式2的值;
依次重复下去,直到表达式2的值=false。
while(逻辑表达式){ 语句; ... ; }
执行过程:先判断逻辑表达式的值。若=true,则执行其后面的语句,然后再判断条件并反复执行,直到条件不成立为止。
break 用于终止某个语气块的执行。用在循环体中,可以强行退出循环
continue 用在循环语句体中,用于终止某次循环过程,跳过循环体中continue语句下面未执行的循环,开始下一次循环过程
switch
1、小心case穿透,用break结束,否则会穿到下一句
2、多个case可以合并在一起 3、default不省略
4、Java中的switch语句只能探测到int类型
方法(其他语言叫函数)
本质:用来完成特定功能的代码片段,增强程序的复用性
形式参数:方法被调用时用于接收外界输入的数据。
实参:调用方法时实际传给方法的数据。
返回值:方法在执行完毕后返还给调用它的环境。
返回值类型:事先约定的返回值的数据类型,若无返回值,必须给返回值类型void
return:方法返回
基本类型传递的是该数据本身。引用类型传递的是对对象的引用,而不是对象本身。
Java不是一步一步过程,考虑应该具有哪些对象 一个方法必须通过对象才能调用
类:用于描述同一类型的对象的一个抽象的概念,具有动态和静态属性。
对象可以看作是一个具体的实例;对象是Java核心,定义类才有对象;对象可以看作是静、动态属性的封装体
思想:1、考虑有哪些类和哪些对象 2、类和对象有哪些属性
3、它们之间的关系、方法
成员变量:1、可以是任何一种数据类型(包括基本类型和引用类型)
2、作用范围是整个类体 3、定义时可以进行初始化,如果不对其初始化,使用默认null(0)初始化
引用类型:基本类型之外的都是引用类型(小块内存指向大块内存)
new出来的存放在堆内存
对象的创建和使用
1、必须使用new的关键字创建对象 2、使用对象(引用).成员变量或来引用对象的成员变量
3、使用对象(引用).方法(参数列表)来调用对象的方法
4、同一类的每个对象有不同的成员变量存储空间
5、同一类的每个对象共享该类的方法。非静态方法时针对每个对象进行调用
构造方法
1、使用new+构造方法创建一个新的对象
2、构造函数是定义在Java类中的一个用来初始化对象的函数 3、构造函数与类同名且没有返回值
约定俗成的命名规则
1、类名的首字母大写 2、变量名和方法名的首字母小写 3、运用驼峰标识
方法的重载:指的是一个类中可以有相同的名字,但参数不同的多个方法。调用时,会根据不同的参数表选择对应的方法。
this关键字
1、在类的方法定义中使用this关键字代表使用该方法的对象的引用
2、当必须指出当前使用方法的对象是谁时要使用this
3、有时使用this可以处理方法中成员变量和参数重名情况
4、this可以看作时一个变量,它的值时当前对象的引用(指向自己)
static关键字
1、在类中,用static声明的成员变量为静态成员变量,它为该类的公用变量,在第一次使用时被初始化,所以对该类的对象
来说,static成员变量只有一份
2、用static声明的方法是静态方法,在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可以访问非static
成员(静态方法不再是针对某个对象调用,所以不能访问非静态成员)
3、可以通过对象引用或类名访问静态成员
package和import语句
为了便于管理大型软件系统中数目众多的类,解决类的命名冲突问题,Java引入包(package)机制,提供类的多重命名
空间(写在第一行)
package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包(若缺该语句,则指定为无名包)
格式:package pkg1[.pkg2[.pkg...]]
Java编译器把包对应于文件系统的目录管理,package语句中,用 '.' 来指明包(目录)的层次
例如:package com.wn; 文件的类位于 .\com\wn目录下
注:执行一个类需要写全包名
类的继承与权限控制
通过继承,子类自动拥有了基类(superclass)的所有成员(成员变量和方法)
Java只支持单继承,不允许多继承;一个子类只能有一个基类,一个基类可以派生多个子类
访问控制:对于class的权限修饰只可以用public和default
public可以在任意地方被访问;default类只可以被同一包内部的类访问
方法的重写
1、在子类中可以根据需要对基类中继承来的方法进行重写
2、重写方法必须和被重写方法具有相同方法名称、参数列表和返回类型
3、重写方法不能使用比被重写方法更严格的访问权限
super关键字 用来引用基类的成分
继承中的构造方法
1、子类的构造过程中必须调用基类的构造方法
2、子类可以在自己的构造方法中使用super调用其基类的构造方法
子类可以在自己的构造方法中使用 this调用本类另外的构造方法
3、如果子类的构造方法中没有显式调用基类构造方法,则系统默认调用基类无参数构造方法
4、如果子类构造方法中没有显式调用基类的构造方法,而且基类又没有无参的构造方法,则编译出错
5、如果调用super,必须写在子类构造方法的第一行
object类:是所有Java类的根基类
如果在类的声明中未使用extends关键字指明其基类,则默认基类为object类
对象转型 casting
一个基类的引用类型可以"指向"其子类的对象
一个基类的引用不可以访问其子类对象新增的成员(方法和属性)
可以使用引用变量instanceof类名来判断该引用型变量所“指向”的对象是否属于该类或该类的子类
子类的对象可以当作基类的对象来使用称作向上转型(upcasting),反之称为向下转型(downcasting)
动态绑定和多态 TestPoly/Test java
动态绑定是指在执行期间(而非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法
多态的条件:1、要有继承 2、要有重写 3、父类引用指向子类对象
抽象类
用abstract关键字来修饰一个类或方法时,这个类叫做抽象类或方法
含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须被重写
抽象类不能被实例化;抽象方法只需声明,而不需实现
final关键字
final的变量的值不能被改变 final的方法不能被重写 final的类不能够被继承
接口(interface)是抽象方法和常量值的定义的集合;从本质上讲,接口是一种特殊的抽象类,这种抽象类中
只包含常量和方法的定义,而没有变量和方法的实现
1、多个无关的类可以实现同一个接口 2、一个类可以实现多个无关的接口
3、与继承关系类似,接口与实现类之间存在多态性
接口特性:1、接口可以多重实现(多继承) 2、接口的声明的属性默认且只能是public static final
3、接口只能定义抽象方法,这些方法默认为public的,也只能是public的
4、接口可以继承其他的接口,并添加新的属性和抽象方法
观察错误的名字和行号最重要,要敢于调试
Java异常时Java提供的用于处理程序中错误的一种机制。所谓错误是指在程序运行的过程中发生的一些异常事件
如:除0溢出、数组下标越界、所要读取的文件不存在
设计良好的程序应该在异常发生时提供处理这些数据的方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果
Java程序的执行过程中如果出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息并将被提交给了
Java运行时系统,这个过程称为抛出(throw)异常
当Java运行时系统接受到异常对象时,会寻找处理这一异常的代码,并把当前异常对象交给其处理,这一过程称为捕获(catch)
异常
try尝试执行 可以跟多个catch
Error:称为错误,由Java虚拟机生成并抛出,包括动态链接失败、虚拟机错误等,程序对其不做处理
Exception:异常类的的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显式的声明或捕获
Runtime Exception:一般特殊的异常,如被0除、数组下标超出范围等,其产生比较频繁,处理麻烦,显式的声明或捕获
将会对程序可读性和运行效率影响很大。因此系统自动检测并将它们交给缺省的异常处理程序(用户可不必对其处理)
try语句
try{.......}语句指定了一段代码,该段代码就是一次捕获并处理例外的范围。在执行过程中,该段代码可能会产生并抛出一种或几种类型
的异常对象,它后面的catch语句要分别对这些异常做相应的处理。如果没有例外产生,所有catch段都被略过不执行
catch语句
在catch语句块中是对异常进行处理的代码,每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常处理
在catch中声明的异常对象(catch (SomeException))封装了异常事件发生的信息,在catch语句中可以使用这个对象的一些方法
获取这些信息
例如:getMessage()方法,用来得到有关异常事件的信息
printStackTrace()方法,用来跟踪异常事件发生时执行堆栈的内容
finally语句
finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态作统一的管理
无论try所指定的程序是否抛出例外,finally所指定的代码都要被执行,通常在finally语句中可以进行资源的清除工作
如:关闭打开的文件、关闭临时文件
异常的捕获和处理
Java的例外处理机制使得例外事件沿着被调用的顺序往前寻找,只要找到符合该例外种类的例外处理程序
使用自定义的异常
1、通过继承Java.lang.Exception类声明自己的异常类
2、在方法适当的位置生成自定义异常的实例,并用throw语句抛出
3、在方法声明部分用throws语句声明该方法可能抛出的异常
声明并抛出异常
注:重写方法需要抛出与原方法所抛出异常类型一致或不抛出异常
数组概念:1、数组可以看成是多个相同类型数据组合,对这些数据的统一管理
2、数组变量属于引用类型(不在栈内存,在堆内存),数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量
3、数组中的元素可以在任何数据类型,包括基本类型和引用类型
数组对象的创建
Java中使用关键字new创建数组对象,格式为:数组名 = new 数组元素的类型 [元素个数]
例如:int[] s; s = new int[5];
元素为引用数据类型的数组:每一个元素都需要被实例化
数组初始化
动态初始化:数组定义与为数组元素分配空间和赋值的操作分开进行,即先分配空间再往里赋值
如:int a[] = {9,9,6}; (内部执行过程省略)
数组元素的默认初始化
数组是引用类型,它的元素相当于类的成员变量,因此数组分配空间后,每个元素也按照成员变量的规则被隐式初始化
数组元素的引用
定义并用运算符new为之分配空间,才可以引用数组中的每个元素
数组元素的引用方式:arrayname[index],index为数组元素下标,可以是整型常量或整型表达式,如:a[3]、b[i]、c[6*i]
数组下标从0开始;长度为n的数组合法下标取值范围为:0~n-1
每一个数组都有一个属性length指明它的长度 如a.length的值为数组a的长度(元素个数)
注:搜索建立在排好序的基础之上
二维数组(可以看成以数组为元素的数组)
Java中多维数组的声明和初始化应该从高维到低维的顺序进行
数组的拷贝:使用Java.lang.System的静态方法
String类(不可变) java.lang.String类代表不可变的字符序列
StringBuffer(可变)常用方法
重载方法:public StringBuffer append(...)可以为该StringBuffer对象添加字符序列,返回添加后的StringBuffer对象引用;
例:public StringBuffer append(String Str)
方法 public StringBuffer delete(int Start,int end)可以删除从start开始到end-1为止的一段字符序列,返回修改后的该StringBuffer
对象引用
方法 public StringBuffer reverse()用于将字符序列逆序,返回修改后的该StringBuffer对象引用
基础数据类型包装类
包装类:(如:Interger、Double等)这些类封装了一个相应的基础数据类型数值,并且为其提供了一系列操作
以Java.lang.Interger类为例,构造方法:Interger(int value)
Interger(String s)
Math类(用的不多)
java.lang.Math提供了一系列静态方法用于科学计算
如 abs 绝对值、sqrt 平方根、pow(double a,double b) a的b次幂、random()返回0.0到1.0的随机数
File类
java.io.File类代表系统文件名(路径和文件名)、
File类常见的构造方法:
public File(string pathname)从pathname为路径创建File对象,如果pathname是相对路径,则默认的当前路径在
系统属性user.dir中储存
public File(String parent,String child)以parent为父路径,child为子路径创建File对象
File的静态属性 String separator存储了当前系统的路径分隔符
枚举类型:
1、只能够取特定值中的一个 2、使用enum关键字
3、java.lang.Enum类型 例如:TestEnum.java
定义:Java API所提供的一系列类的实例,用在程序中存放对象
J2SDK所提供的容器API位于Java.util包内

collection接口定义了存取一组对象的方法,其子类接口Set和List分别定义了存储方式
Map接口定义了存储“键(key)——值(value)映射对”的方法
Collection 方法举例
容器类对象在调用remove、contains等方法时需要比较对象是否相等,这会涉及到对象类型的equals方法和hashCode;
对于自定义的类型,需要重复equals和hashCode方法以实现自定义的对象相等规则
注意:相等的对象需要具有相等的hashCode
Iterator接口
所有实现了collection接口的容器类都有一个Iterator方法用以返回一个实现了Iterator接口的对象
Iterator对象称作迭代器,用以方便地实现对容器内元素的便利操作
Iterator接口定义了如下方法:
boolean hasNext(); //判断游标右边是否有元素
Object next; //返回游标右边的元素并将游标移到下一个位置
void remove(); //删除游标左面的元素,在执行完next之后该操作只能执行一次
Set接口
Set接口时Collection的子接口,Set接口没有提供额外的方法,但实现了Set接口的容器类中的元素是没有顺序的,而且不可以重复
Set容器可以与数学中的“集合”概念相对应
J2SDK API中所提供的Set容器类有HashSet、Treeset等
List算法 java.util.Collections提供了一些静态方法实现了基于List容器中的一些常用算法
void sort(List) 对List容器内的元素排序
void shuffle(List) 对List容器内的对象进行随机排列
void reverse(List) 对List容器内的对象进行逆序排列、
void fill(List,Object) 用一个特定的对象重写整个List容器
void copy(List dest,List src) 将scr List容器内容拷贝到dest List容器
int binarySearch(List,Object) 对于顺序的List容器,采用折半查找的方法查找特定对象
Comparable接口
所有可以“排序”的类都实现了java.lang.Comprable接口,Comparable接口
Comparable接口中只有一个方法:public int compareTo(Object obj);
该方法:返回0表示 this==obj 返回正数表示 this>obj
返回负数表示 this<obj
实现了Comparable接口的类通过实现comparaTo方法从而确定了该类对象的排序方法
如何选择数据结构
衡量标准:读的效率和改的速度 Array读快改慢 Linked改快读慢 Hash两者之间
Map接口
实现Map接口的类用来存储键——值对
Map接口的实现类有HashMapheTreeMap等
Map类中存储的键——值对通过键来标识,所以键值不能重复
Auto - boxing/unboxing
1、在合适的时机自动打包、解包 2、自动将基础类型转换为对象
3、自动将对象转换为基础类型
JDK1.5泛型
起因:JDK1.4以前类型不确定,装入集合的类型都被当做Object对待,从而失去了自己的实际类型
从集合中取出时往往需要转型,效率低,容易产生错误
解决办法:在定义集合的时候同时定义集合中对象的类型
实例:BasicGeneric.java可以在定义collection的时候指定,也可以在循环时用Iterator指定
好处:增强了系统的可读性和稳定性
总结:一个类(Collection)三个知识点(For、Generic、Auto—boxing/unboxing)六个接口
在Java程序中,对于数据的输入/输出操作以“流”(stream)方式进行;J2SDK提供了各种各样的“流”类,
用以获取不同种类的数据;程序中通过标准的方法输入或输出数据
输入/输出流的分类
java.io包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同的角度对其进行分类;
按数据流的方向不同,可以分为输入流和输出流
按处理数据单位不同,可以分为字节流和字符流
按照功能不同,可以分为节点流和处理流
|
字节流
|
字符流
| |
|
输入流
|
InputStream
|
Reader
|
|
输出流
|
OutputStream
|
Writer
|
节点流和处理流
节点流为可以从一个特定的数据源(节点)读写数据(如:文件、内存)
处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据处理为程序提供更为强大的读写功能
InputStream
继承来自InputStream的流都是用于向程序中输入数据,且数据的单位字节(8 bit)
Reader 继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16 bit)
Writer 继承自Writer的流都是用于程序中输出数据,且数据的单位为字符(16 bit)
节点流类型
|
类型
|
字符流
|
字节流
|
|
File(文件)
|
FileReader
FileWriter
|
FileInputStream
FileOutputStream
|
|
Memory Array
|
CharArrayReader
CharArrayWriter
|
ByteArrayInputStream
ByteArrayOutputStream
|
|
Memory String
|
StringReader
StringWriter
|
——
|
|
Pipe(管道)
|
PipeReader
PipeWriter
|
PipeInputStream
PipeOutputStream
|
缓冲流
缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加一些新的方法
缓冲输入流支持其父类的mark和reset方法
BufferedReader提供了readLine方法用于读取一行字符串(以\r或\n分隔)
BufferedWriter提供了newLine用于写入一个行分隔符
对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush方法将会使内存中的数据立刻写出
Print流
PrintWriter和PrintStream都属于输出流,分别针对字符与字节
PrintWriter和PrintStream提供了重载的print;Println方法用于多种数据类型的输出
PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
PrintWriter和PrintStream有自动flush功能
Object流 直接将Object写入或读出
线程是一个程序内部的顺序控制流(一个程序不同的执行路径)
线程和进程的区别:
1、每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销
2、线程可以看作轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,线程切换的开销小
3、多进程:在操作系统中能同时运行多个任务(程序)
4、多线程:在同一个应用程序中有多个顺序流同时执行
Java的线程是通过java.lang.Thread类实现的
VM启动时会有一个由主方法(public static void main(){})所定义的线程
可以通过创建Thread的实例来创建新的线程;每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作,方法run()称为线程体
通过调用Thread类的start()方法来启动一个线程
线程控制基本方法
|
方法
|
功能
|
|
isAlive()
|
判断线程是否还“活”着,即线程是否还未终结
|
|
getPriority()
| 获得线程的优先级数值 |
|
setPriority()
|
设置线程的优先级数值
|
|
Thread.sleep()
|
将当前线程睡眠指定毫秒数
|
|
join()
|
调用某线程的该方法,将当前线程与该线程“合并”,即让出CPU,当前线程进入就绪队列等待调度
|
|
wait()
|
当前线程进入对象的wait pool
|
|
notify()/notifyall()
|
唤醒对象的wait pool中的一个/所有等待线程
|
sleep方法
可以调用Thread的静态方法:public static void sleep(long millis)throws InterruptedException使得当前线程休眠(暂时停止执行millis毫秒)
由于是静态方法,sloop可以由类名直接调用:Thread。sleep(...)
join方法 合并某个线程 例:Thread/TestJoin.java
yield方法 让出CPU,给其他线程执行的机会 例:Thread/TestYield.java
线程同步
在Java语言中,引入了对象互斥锁的概念,保证了共享数据操作的完整性,每个对象对应于一个可称为“互斥锁”的标记,这个标记保证在任意时刻,
只能有一个线程访问该对象
关键字synchronized来与对象的互斥锁联系,当某个对象synchronized修饰时,表明该对象在任一时刻只能由一个线程访问
wait sleep区别
wait识别的线程可以访问锁定对象,调用wait方法时必须锁定该对象
sleep识别的线程也不可以访问锁定对象
通信协议分层的思想
为什么要分层? 由于节点之间联系很复杂,在制定协议时,把复杂成分分解成一些简单的成分,再将它们复合起来。最常用的复合方法是层次方式,
即同层间可以通信,上一层可以调用下一层,而与下一层不发生关系。各层互不影响,利于系统的开发和拓展
通信协议的分层规定
把用户应用程序作为最高处,把物理通信线路作为最底层,将其间的协议处理分为若干层,规定每层处理的任务,也规定每层的接口标准
|
ISO参考标准
|
TCP/IP参考模型
|
|
应用层
|
应用层
|
|
表示层
|
传输层
|
|
会话层
|
网络层
|
|
传输层
|
物理+数据链路层
|
|
网络层
| |
|
数据链路层
| |
|
物理层
|
IP协议(提供了独一无二的IP地址)
IP(Internet Protocol)协议是网际层的主要协议,支持网间互连的数据报通信。
主要功能有:1、无连接数据报传送 2、数据报路由选择和差错控制
TCP(transmission control protocol)协议
专门设计用于在不可靠的因特网上提供可靠的、端到端的字节流通信的协议。它是一种面向连接的协议。
TCP连接是字节流而非报文流
UDP(user data protocol)UDP向应用程序提供了一种发送封装的原始IP数据报的方法,并且发送时无需建立连接(不可靠)
TCP、UDP端是分开的,每一个有65536个端口
Socket
两个Java应用程序可通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket
Socket通常用来实现client—sever连接
java.net包中定义了两个类Socket和SeverSocket,分别用来实现双向连接的client和sever
建立连接时所需的寻址信息为远程计算机的IP地址和端口号(Port number)
ClassLoader的类加载机制:并非一次性加载,需要的时候加载(运行期间动态加载)
例:TestDynamicLoading java-verbose:class 可以观察类的加载过程
static语句块在加载后执行一次 dynamic语句块每次new新的对象都会执行(等同于构造方法中语句,用的较少)
JDK Class Loader的层次关系(不是继承)
classloader在load class的时候首先找到上一层loader是不是load过了,如果已经load,就不会再load
安全性好,自己写的String.class永远没有机会执行(破坏性的代码)
2496

被折叠的 条评论
为什么被折叠?



