疯狂Java摘要
1.语言零碎基础知识
<1>.Windows中系统变量有系统变量和用户变量之分,就是作用域大小的区别
<2>.Ruby:弱类型,最大的特点就是简洁。Python:语言简洁语法清晰
<3>.每一个函数方法都有一个方法栈
<4>.看待每一个对象都可以分为两部分,一部分在栈区,一部分在堆区
<5>.方法复写时要注意“两小一大”原则
- a.子类方法返回值类型要小于等于父类
- b.类方法要么不抛出异常,要么抛出父类异常或者子类。
- c.子类方法的访问权限要大于等于父类
<6>.子类同名实例变量不会覆盖父类的,只是简单的隐藏了父类的实例变量
<7>.instanceOf()
判断的是前面对象是否是后边类或者后边类的子类的实例。t.getClass() == Person.class
则不包含子类
<8>.继承和组合:前者会开辟两份父类变量的内存空间;后者子类和父类对象内存空间各一份,只需要多一个引用变量。这就是著名的is-a和has-a关系
<9>.工厂设计模式建议一个A类组合B类时最好面向接口,将A类和B类完全分离,建立B对象的逻辑交给工厂,当对B类进行扩展时完全不影响A类
<10>.Java8新特性:接口中允许添加默认方法,默认方法可以提供方法实现
<11>.Java8新特性:局部内部类访问局部变量时不用我们用final修饰,其实这个变量会默认被final修饰,所以同样我我们不能多次对她赋值
<12>.Java8新特性:Lambda表达式允许使用简洁代码创建只有一个方法的接口实例对象,省略了要复写方法名与修饰符和new对象的语句。使用简写规则如下:
- a.允许省略形参的类型,如果形参列表只有一个参数,那么小括号也能省略。
- b.代码块中只有一条语句,可以省略代码块的大括号。如果这仅有的一条语句还是返回语句,那么return也能省略
- c.不带形参的直接写对小螺号即可。
<13>.直接量赋值字符串变量,常量池会缓存字符串直接量。
String srr1 = "雾雨魔理沙";
String str2 = "雾雨魔理沙";
String str3 = "雾雨"+"魔理沙";
str1 == str2 == str3;
<14>.大类型强转为小类型可能会造成信息丢失(long --> int 会丢失前32位的数据)
<15>.不常用关键字:assert
、goto
、transient
、stictfp
、volatitle
、const
<16>.Jar:Java Archive File(Java档案文件)
<17>.Obejct对象的clone()
方法:这是浅层的克隆,此克隆方法只克隆该对象所有成员变量值,不会对引用数据类型成员变量引用的对象进行克隆
<18>.Java7特性:新增了ThreadLocalRandom,相比Random可以减少多线程资源竞争,最终保证系统具有良好的线程安全,功能与使用与过去的Random相同
<19>.Random使用注意:Random对象本身使用一个48位的种子创建,对她们一同样的顺序调用方法,则她们产生相同的数字序列
<20>.在Java中如果对浮点数进行算术运算时不可直接计算,结果会发生精度丢失,可以把浮点数封装到BigDecimal中进行计算,封装时不可使用构造函数new BigDecimal(double d)
,可以使用new BigDecimal(String s)
或者BigDecimal.valueOf(double d)
来封装浮点数,再进行计算,或者计算浮点数的方法用 Strictfp
关键字来修饰
<21>.Calendar对象的set()
方法有延迟修改的特性,除非你调用get()、getTime()、getTimeMillis、add()、roll()是才会重新计算日历的时间,把特殊的时间修正正确,如8月31日你修改成9月31日。
2.垃圾回收机制篇
<1>.优点:如果没有此机制,无论是忘记回收还是错误的回收都会导致系统的崩溃
<2>.缺点:机制的开销影响程序的性能
<3>.特点:
- a.只能回收内存资源,对物理资源无力
- b.让对象引用指向null,只是暗示回收机制回收此对象
- c.Runtime()和System.gc()回收开启仅仅是建议系统这样做。
<4>.垃圾回收机制只负责回收推内存中的对象,回收对象之前,总会调用它的finalize()
方法,该方法可能让对象重新复活,从而取消垃圾回收机制
<5>.流程:对象被回收时分为三个状态:
- a.可达状态,一般状态,不可被回收
- b.可恢复状态,对象没有被引用,并且
finalize()
方法未被调用 - c.不可达状态,彻底失去引用,会被垃圾回收机制回收
<6>.可通过Runtime.getRuntime().runFinalization()
或者System.runFinalization()
强制垃圾回收机制调用对象的finalize()方法,不过这之前要先调用System.gc()
或者Runtime.getRuntime().gc()
来开启gc()才可以。
//可用如上这种写法保证单例对象永远不为空(待测试)
class NewInstance{
private static NewInstance instance = new NewInstance();
private NewInstance(){}
public static NewInstance getInstance(){
return instance;
}
public void finalize(){
instance = this;
/*
System.gc();
System.runFinalization();可用这两个方法强制调用对象的finalize()方法
*/
}
}
<7>.4中常见引用
- 强引用:我们一般定义的引用都是强引用
- 软引用:通过SoftReference类来实现,一个对象只有软引用时,系统内存空间足够时不会被回收,当系统空间不足时可能会被回收
- 弱引用:通过WeakReference类来实现,比软引用还弱的引用,一个对象只有弱引用时,不管系统内存空间是否足够都有可能被回收
- 虚引用:通过PhantomReference类来实现,如果一个对象只有一个虚引用时那么它和没有引用效果大致相同。虚引用主要用于跟踪垃圾回收的状态,虚引用不能单独使用,必须与引用队列ReferenceQueue联合使用。
代码:
软引用或者弱引用的使用方法:
WeakReference weakRef = new WeakReference(new String("弱引用"));
weakRef.get();//返回值为字符串,不会导致内存紧张的情况下其实这里一般不会回收
System.gc();
System.runFinalization();
weakRef.get();//返回值可能为null,垃圾回收机制回收了引用
虚引用的使用方法:
ReferenceQueue queue = new ReferenceQueue();//引用队列
PhantomReference phantomRef = new PhantomReference(new String("虚引用"),queue);
phantomRef.get();//返回值为null,不能获取虚引用的引用对象
Runtime runtime = Runtime.getRuntime;
runtime.gc();
runtime.runFinalization();
queue.poll() == phantomeRef;//比较结果为true。垃圾回收完,引用存放在了引用队列中,取出最先进入队列的引用
3.集合框架
<1>.Java8新特性:Iterable接口添加了void forEach(Consumer action)
方法,Collection体系也从而有了这个方法,Consumer是一个函数式接口。foreach()方法会把集合元素传递给Comsumer处理。所以可以写成如下形式:
list.forEach(obj -> System.out.println("方法1,迭代的集合元素是:"+ obj);
<2>.Java8新特性:通过Iterator接口的默认方法void forEachRemaining(Consumer action)
forEachRemaining(obj -> System.out.println("方法2,迭代的集合元素是"+obj))
<3>.Collection集合新增removeIf(Predicate fileter)
方法,将符合fileter条件的元素全部删除,Predicate也是一个函数式接口,可写成如下形式
list.remove(filter -> ((String)fileter).length() > 5)
注:Predicate有一个test(Object o)方法,可以检测数据是否符合自己的规则,规则通过复写接口的抽象方法传递。
<4>.Colleation接口新增默认方法sream()获取操作该集合的流式对象,集合通过流式API处理集合.
流式API有Stream、IntStream、LongStream、DoubleStream
等常用,这种流式操作分为中间方法和末端方法,中间方法一般会返回一个流;末端方法是流的最终操作,只能执行一次这种方法。具体流式方法可去查询API并且练习使用
<5>.EnumSet类,是一个专门为枚举设计的集合类,线程不同步,集合元素是有序的,排序方式通过枚举值在集合内的定义顺序作为集合元素的顺序。内部以位向量形式存储,非常紧凑高效,占用内存小,运行效率好,不可插入null
<6>.Arrays.asList(Object... o)
返回的list不是ArrayList的实现类,而是Arrays的内部类ArrayList的实例,这是一个固定长度的List集合,只能遍历,不能增删。
<7>.TreeMap 的排序作用的Map中的Key,与value无关。
<8>.一个Map的key值为null,其实这就是一个Set集合
<9>.WeakHashMap 的 key只保留实际引用的弱引用,垃圾回收可能回收键值。前提是该key所引用的对象不被任何强引用引用,如果key的值是字符串,那么定义为【"java"】这种形式,其实"java"直接量已经被系统强引用
<10>.IdentityHashMap 基本与HashMap一样,不过当她判断两个key是否相等时,当且仅当key1==key2时,IdentityHashMap才认为两个key相同
<11>.**EnumMap **内部以数组形式保存,实现形式非常紧凑、高效。根据Key的自然顺序(枚举值得定义先后顺序)进行的排序
<12>.Collections 有多个synchronizedXxx()
方法来同步集合,并且可以通过unmodifiableXxx()、emptyXxx()、singletonXxx()
获取一个不可变集合,修改此集合会抛出UnsupportedOperationException()
<13>.Queue集合,模拟队列的数据结构。有3个添加的方法,3个取出的方法,和2个查询队头元素的方法
- a.PriorityQueue,队列实现类,按照队列元素的大小顺序进行排序的队列,取出时取出的是最小元素。当热也可以通过Comparable定制排序规则
- b.Deque接口是Queue的子接口,这是一个双端队列,可以从两端任意一段存或取数据的集合
- c.ArrayDeque基于数据的双端队列,指定队列长度,如果不指定队列默认长度为16。当程序需要使用栈这种数据结构时推荐使用此对象
<14>.注意:
- a.底层数组随机访问性能会很好,链表结构插入和删除性能很好。总体来说ArrayList性能优于LinkedList,优先考虑ArrayList
- b.遍历集合时数组数据结构的采用随机访问形式遍历集合(get(index)),对于链表结构使用迭代器的方式
- c.如果有多个线程访问集合,开发者考虑到线程安全,可以使用Collections将集合包装成线程安全的集合
4.泛型
<1>.Java7支持菱形语法,不需要带完整的泛型信息,只有给出一対<>尖括号即可。
<2>.2.父类定义了泛型,子类继承父类,父类要么不能包含类型形参,要传入实际参数;或者包含类型形参,不过子类也要包含类型形参。如下两种写法
class GenericSon extends GenericSon{}
class GenericSon extends GenericSon{}
3.Person
4.Object[] arr = new String[];
这种写法编译能通过,不过就算能通过也不要这样表示,没有意义
5.泛型的上限可通过【&】符号指定多个且的关系,如:class Apple
6.泛型方法其实就是在方法签名处定义方法泛型供整个方法使用
7.按理说只要是使用通配符的地方同样也能写成泛型方法,如果方法多个参数之间类型有依赖关系或返回值与参数之间的依赖关系应该使用泛型方法;如果没有这种依赖关系,则可以使用通配符【?
】
9.泛型有擦除的特性,如下语句不会报错,能够正常运行。当执行第三局时list集合的泛型类型Integer已经被擦除,这样做集合不能获取元素会发成ClassCastException,不过能存入元素
List list = new ArrayList();
list.add(1);
List objList = list;
List stringList = objList;
stringList.add("帕秋莉·诺蕾姬");
5.异常相关
<1>.Java7特性:支持多异常捕获,一个catch可以处理多个异常,写法如下:并且注意这个异常变量是被final修饰,一般单异常处理的catch不用final修饰
catch(IndexOutOfBoundsException | NumberFormatException e){}
<2>.Java7特性:自动关闭资源的try语句,不过这些资源需要实现AutoCloseable或Closeable接口,我们不用写关闭资源的语句,自动关闭资源。Java 7重写了所有资源类
try(FileReader fr = new FileReader(path);FileWriter fw = new FileWriter(path)){
//方法体,并且fr和fw这两个流在代码运行完毕或者异常错误后都会自动关闭
}catch(IOException e){}
<3>.异常链:把原始异常异常信息隐藏起来,仅向上提供必要的异常提示信息的处理方式,可以保证底层异常不会扩散到表现层,符合面向对象的封装设计。实现就是捕获一个异常然后抛出另一个异常。----责任链设计模式
public void calsal() throws SalException{
try{
//义务逻辑
}catch(SQLException e){
//把原始异常记录下来,留给管理员
throw new SalException("访问底层数据库出现异常");
}
}
<4>.Java的异常跟踪栈,大多数复杂的操作都会被分解成一系列方法调用。异常打印一般都是把跟踪栈中的异常全部打印出来,保持跟踪栈的不断通过 throw new RuntimeException(e)即可。看异常信息一点一点的看,结构是————【at 类名.方法名(Java文件名.java:行数)】
<5>.异常避免过度使用,正常的业务逻辑不要使用异常。Catch All语句不过是一种避免错误处理而加快变成进度的机制,应避免在实际应用中使用这种语句———— catch(Throwable e){}
6.IO流相关
<1>.不常用IO流:AudioInputStream 、 CipherInputStream 、 DeflaterInputStream 、 ZipInputStream
等,访问音频文件 / 加密 / 解密 / 压缩 / 解压功能的流
<2>.Java虚拟机可读取其他进程的数据,通过Runtime.exec("程序名")
来获取Process进程对象,然后可获取子进程流对象
InputStream getErrorStream();获取子进程的错误流
InputStream getInputStream();获取子进程的输入流
InputStream getOutputStream();获取子进程的输出流
<3>.对象序列化步骤:
- a.序列化对象实现 Serializable 接口或者 Externalizable 接口
- b.通过 ObjectOutputStream 来把对象序列化到本地;通过 ObjectInputStream 来读取序列化到本地的对象
注意:
- a.如果序列化对象成员有引用数据类型的变量,那么这个引用的对象也要是能序列化的,否则该对象不能进行序列化操作。
- b.每一个序列化的对象都有一个序列化编号,如果该对象序列化过,那么程序不会再次序列化该对象,而是直接引用这个序列化编号
- c.由于这个引用现象的出现,所以序列化可变对象时,序列化的对象数据是第一次writeObject()的数据,之后改变数据写入多少遍该序列化的数据都是第一次的数据
- d.使用关键字 transient 修饰的成员,可以在序列化时无视这个成员
- e.可以自定义序列化逻辑
<4>.Java 1.4新增NIO概念,非常重要,非阻塞式IO流,以后一定要看一下。并且在Java 1.7中新增NIO2的感念,有递归目录的简易方法,一定要看一下。
<5>.Charset类,字符集Charset相关API
static charset forName(String str); 获取字符集对象
CharsetEncoder newEncoder(); 返货字符编码器,通过encode(CharBuffer buf)编码字符
CharsetDecoder newDecoder(); 返回字符解码器,通过decode(ByteBuffer buf)解码字节
CharBuffer decode(ByteBuffer bb); 解码字节
ByteBuffer encode(CharBuffer cb); 编码字符
ByteBuffer encode(String str); 编码字符串,与String类的getBytes(String str)一样
<6>.文件锁,可以有效阻止多个进程并发修改同一个文件。大部分系统都提供了文件锁的功能。使用: FileChannel
中提供了lock()/tryLock()
来对文件添加文件锁并且获取到 FileLock
对象。再通过 FileLock
对象的release()
方法释放锁
特点:
- a.
lock()
是阻塞式方法,获取不到文件锁对象将阻塞 - b.
tryLock()
只是尝试锁定文件,锁定文件将返回锁,否则返回null - c.还有
lock(long position,long size,boolean shared)
和tyrLock(long position,long size,boolean shared)
。position是加锁内容开始的位置;size是加锁内容的长度;shared表示该锁是共享锁还是排他锁
示例代码:
class FileLockTest
{
public static void main(String[] args)throws Exception{
try(
FileChannel channel = new FileOutputStream("a.txt").getChannel()
){
//10s中只有主线程能对a.txt文件进行修改
FileLock lock = channel.tryLock();
Thread.sleep(1000);
lock.release();
}
}
}
7.线程相关
<1>.并行性(Parallel):指的是同一时刻,有多条指令在多个处理器上同时执行。并发性(Concurrency):指在同一时刻只有一条指令执行,但多个进程指令快速切换执行。
<2>.程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。
<3>.使用Callable和future创建线程的方式。特点,能获取到线程方法执行完毕后的返回值。执行过程中获取返回值会造成线程阻塞。Future的实现类 FutureTask 有一些方法来获取返回值
class CallableThread
{
public static void main(String[] args){
//使用Lamada表达式来创建一个Callable对象
Callable callable = (Callable)()->{
//Callable中call方法的逻辑,就是线程的逻辑。有返回值
...
return i;
}
//创建Future对象来操作这个callable对象
FutureTask futureTast = new FutureTask(callable);
Thread.sleep(1000);
new Thread(futureTest,"Callable创建线程").start();
Thread.sleep(2000);
//通过get()返回子线程返回值,此方法在线程未执行完毕时调用会阻塞住线程
System.out.println("子线程返回值"+futrueTask.get());
}
}
<4>.线程状态:被创建,就绪,运行,阻塞,消亡。(这里自己过去理解有很大误区!!)
(1)线程被阻塞有如下几种情况:
- a.线程被
sleep()
或者jion()
; - b.调用了阻塞式IO方法
- c.同步监视器正被其他线程持有
- d.线程在等待某一个通知,被wait()了
- e.程序调用了线程的
suspend()
方法将该线程挂起(容易造成死锁,尽量避免使用)
(2)被阻塞的线程解除阻塞后会恢复到就绪状态,等待线程调度器的再次调度,来达到运行状态
(3)线程消亡有如下几种情况:
- a.
run()
或call()
方法执行完毕,线程正常结束 - b.线程抛出一个未捕获的Exception或Error
- c.直接调用该线程的
stop()
方法来结束线程(该方法容易导致死锁,不推荐使用)
(4)一个线程到达消亡状态后将无法被恢复为其他状态,不能start()重新达到就绪状态,否者会抛出IllegalThreadException()
(5)后台线程与前台线程共死。如果前台前台线程全部消亡,后台线程也会随之消。垃圾消息机制就是典型的后台线程。后台线程的子线程也是后台线程
(6)释放同步监视器的锁时机:
- a.同步方法、同步代码块结束
- b.同步方法、同步代码快中出现未处理的Error或Exception
- c.同步方法、同步代码快执行了同步监视器的
wait()
方法,当前线程暂停
(7)Java1.5出现的同步锁Lock
- a.ReadWriteLock(读写锁),允许对共享资源并发访问,实现类有ReentrantReadWriteLock
- b.Lock,实现类为ReentrantLock,此同步锁较为常用
- c.提供方法有
例:
tryLock() 适用于非块结构
lockInterruptibly() 获取终端锁
tryLock(long time,TimeUnit unit); 获取超时失效锁
<5>.线程相关API
isAlive() 当线程处于就绪,运行,阻塞三种状态时返回true;当线程处于新建或者消亡状态时为false。
join() 调用该方法时所在线程将被阻塞,等待被加入的线程执行完毕后才能达到就绪状态。
join(long milles) 阻塞的最长时间是milles
setDaemon(false flag) 设置线程是后台线程
static sleep(long millis)让当前正在执行的线程睡眠
static yield() 让当前正在执行的线程让步(暂停),会达到就绪状态
class ThreadClass extends Thread
{
public void run(){
//线程运行体
for(int x=0 ; x<1000; x++){
System.out.println(Thread.currentThread().getName()+"------"+x);
}
}
public static void main(String[] args)throws Exception{
for(int x=0; x<100; x++){
if(x == 20){
ThreadClass thread = new ThreadClass();
thread.start();
//调用join方法后主线程会等待ThreadClass线程运行完毕后才运行
thread.join();
}
System.out.println(Thread.currentThread().getName()+"------"+x);
}
}
}
<6>.领域驱动设计(DDD,Domain Driven Design)一种流行的面向对象设计方式,认为每个类都应该是完整的领域对象,对自己成员进行计算的操作应该自己定义方法进行,而不是在外部类定义。这样才能保证该对象的完整性与一致性。
<7>.通过使用BlockingQueue来做到线程通讯的目的(不使用同步)
BlockingQueue
是一个线程同步工具,是Queue
的子接口,向队列中存入元素时如果队列已满,该线程将被阻塞;向队列中取出元素时如果队列已空,则该线程被阻塞
方法解析:
添加的方法
<1>.add(e):队尾插入元素,当队列已满时抛出异常
<2>.offer(e):队尾插入元素,当队列已满时方法返回值为false,元素无法存入队列
<3>.put(e):队尾插入元素,当队列已满时方法会阻塞住线程
删除的方法
<1>.remove():队头删除元素,当队列为空时抛出异常
<2>.poll():队头删除元素,当队列为空时方法返回值为false,元素获取为null
<3>.take():队头删除元素,当队列为空时会阻塞住线程
获取不删除的方法
<1>.element():队头获取元素,不删除。队列为空时抛出异常
<2>.peek():队头获取元素,不删除,队列为空时方法返回值为false,元素获取为null
实现类:
<1>. ArrayBlockingQueue 基于数组实现的BlockingQueue队列
<2>. LinkedBlockingQueue 基于链表实现的BlockingQueue队列
<3>. PriorityBlockingQueue 按照元素大小排序的队列,取出来的元素是最小元素,可以使用Comparator进行定制
<4>. SynchronousQueue 同步队列,对该队列的存取操作必须交替进行
<5>. DelayQueue 特殊的BlockingQueue,底层基于 PriorityBlockingQueue 实现,要求集合元素实现Delay接口,其中元素会按getDalay()返回值大小进行排序
代码示例:
class Producer extends Thread
{
private BlockingQueue bq;
public Producer(BlockingQueue bq){
this.bq = bq;
}
public void run(){
String[] arr = new String[]{"Java","Struts","Spring"};
for(int x=0; x<99999999; x++){
System.out.println(Thread.currentThread().getName()+"生产者准备生产集合元素!");
try{
//Thread.sleep(220);
bq.put(arr[x % 3]);
}
catch(Exception e){e.printStackTrace();}
System.out.println(Thread.currentThread().getName()+"生产完成"+bq);
}
}
}
class Consumer extends ThreadClass
{
private BlockingQueue bq;
public Consumer(BlockingQueue bq){
this.bq = bq;
}
public void run(){
while(true){
System.out.println(Thread.currentThread().getName()+"消费者准备消费集合元素");
try{
//Thread.sleep(220);
System.out.println(Thread.currentThread().getName()+"消费完成"+bq.take());
}
catch(Exception e){e.printStackTrace();}
}
}
}
class BlockingQueueTest
{
public static void main(String[] args){
BlockingQueue bq = new ArrayBlockingQueue(4);
new Producer(bq).start();
new Producer(bq).start();
new Producer(bq).start();
new Consumer(bq).start();
}
}
8.网络相关
<1>.URLDecoder 和 URLEncoder 主要用于完成普通字符串和application/x-www-from-urlencoded MIME
字符串之间的相互装换。
- a.URLDecoder 可以把乱码特殊字符串转换为中文字符,是解码的过程。通过
URLDecoder.decode(String str,String enc);
enc为指定字符集 - b.URLEncoder 可以把中文字符装换为特殊字符串,是编码的过程。通过
URLEncoder.encode(String str,String enc);
<2>.URL(Uniform Resource Locator) 对象代表统一资源定位器,指向互联网资源的指针。URI(Uniform Resource Identifiers),这是Java提供的一个类,代表一个统一资源标识符,不能用于定位资源,它的唯一作用就是解析,可以将URL理解成URI的特例,类与对象的那种关系。
<3>.HttpUrlConnection
或者 UrlConnection
一般都要设置很多请求头,具体请参考我的Http笔记。对于get请求一定要建立连接通过 conn.connect();
对于Post请求一定要设置 conn.setDoOutput(true)
和 conn.setDoInput(true)
<4>.IP协议全称 Internet Protocal,通过该协议使Internet成为一个允许连接不同类型的计算机和不用操作系统的网络,其负责将消息从一个主机传送到另一个主机,消息传送过程中给分割成一个个的小包。不过IP协议不能解决数据在传输过程中可能出现的全部问题。所以需要 TCP协议 提供通信服务。TCP协议,提供可靠并且无差错的通信服务。让它们建立一个链接,是一条虚拟链路。TCP协议 有自己的重发机制,提供了可靠的通信连接,适应网上的各种变化。** 综上所述**,这两个协议功能上不尽相同,也可以分开来单独使用,不过她们是在同一时期作为一个协议来设计的,并且功能上也是互补的。所以两者只有结合起来,才能保证Internet在复杂的环境下运行。
<5>.TCP在使用时Socket对象可以设置超时时间,通过setSoTimeOut(s)
或者构造方法的参数。如果超出了该时间限制,那么这些方法就会抛出SocketTimeOutException异常。可以捕获做相应的处理.
<6>.使用ServerSocket如何群发信息。因为Socket与ServerSocket建立连接后,都会在服务端新建一个Socket,那么我们通过记录服务端有多少个新建的Socket既可以向多用户发送信息
<7>.可以使用NIO、AIO、代理服务器Proxy等为Socket服务,前者可做阻塞式Socket,这个以后需要时可以来看一下
9.反射相关
<1>.类加载器负责将.class文件加载到内存中,并生成 java.lang.Class
对象。JVM 启动时,会形成由三个类加载器组成的初始类加载器层次结构
- a.Bootstrap ClassLoader:根类加载器,负责加载Java的核心类,不是 java.lang.ClassLoader 的子类,有JVM自身实现。诸如——rt.jar等文件
- b.Extension ClassLoader:扩展类加载器,负责加载JRE的扩展目录中的Jar包
- c.System ClassLoader:系统类加载器,负责在JVM启动时加载来自java命令的-classpath或者java.class.path系统属性
<2>.URLClassLoader 类是系统加载器和扩展类加载器的父类,能够从本地文件系统或者远程主机获取二进制文件来加载类。
<3>.Java8新特性:新增的方法参数反射
以上是全部笔记,我怀疑自己只有很久以后才会再回来看Java了,这是第几次看基础知识了....