按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类
JAVA常用的节点流:
常用处理流(关闭处理流使用关闭里面的节点流)
字节流和字符流:
stream结尾都是字节流,reader和writer结尾都是字符流 两者的区别就是读写的时候一个是按字节读写,一个是按字符。 实际使用通常差不多。 在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。 只是读写文件,和文件内容无关的,一般选择字节流。
泛型仅仅是java的语法糖,它不会影响java虚拟机生成的汇编代码,在编译阶段,虚拟机就会把泛型的类型擦除,还原成没有泛型的代码,顶多编译速度稍微慢一些,执行速度是完全没有什么区别的.
使用泛型的好处
1,类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。
2,消除强制类型转换。 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。
3,潜在的性能收益。 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。由于泛型的实现方式,支持泛型(几乎)不需要 JVM 或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。
在Java里,只有值传递,因为引用本身就是一个地址值,我们说的”传递引用“本质上也是“值传递”,只不过传递的是地址值。
在方法中,改变一个对象参数的引用不会影响到原始引用。这是很自然的。
举个例子,假设在函数外有 A a = new A();那么引用a指向堆中的一个对象A()。
假设有一个函数:
void f(A a) {
a = new A();
}
显然,这里a指向了堆中的另一个对象A(),而在函数外的那个引用a依然没有改变,指向原来的对象A()。
计算机本身储存的就是补码:
那么10的补码就是10的原码:0000 0000 0000 1010——这是补码,因为现在是计算机在计算
~10的补码就是:1111 1111 1111 0101
~10的反码就是:1111 1111 1111 0100——补码减1
~10的原码就是:1000 0000 0000 1011——反码取反:这个才是正常二进制数,换算为整数为-11
原码才可以对应为正常的整数,补码只有转换为原码才能被正常人类识别。
已知负数的补码,求负数:
补码-1=反码,反码按位取反=该负数绝对值
已知负数,求负数的补码:
1、负数原码除了符号位,按位取反(不含符号位),加1。
2、负数绝对值的补码(也就是原码),按位取反(含符号位),加1
所以这一题中short a = 0000 0000 1000 0000
强转为byte后,截去高八位 变成 1000 0000 符号位为1,所以为负数,由于计算机存储的是补码,所以就是已知负数
的补码然后求负数的情况
反码:1000 0000 - 1 = 0111 1111
原码:反码按位取反得到 1000 0000,即128(该负数的绝对值),因为是负数,所以结果是-128
(ps:byte中本应该表示“-0”的原码规定为代表-128,有符号的byte类型也就能够表示的范围是-128-127)
采用同样的方法: a = 0111 1111 b = 0111 1111
则a和b的补码都是0111 1111(因为两者都为正数),因为计算机计算的时候是用补码计算的,所以
a = 0111 1111 + 0111 1111 = 1111 1110(结果是补码,java中整数都是有符号类型的,所以判定是负数),也就变成上面的已知负数的补码求负数的过程了 反码 = 补码 - 1 = 1111 1101 该负数的绝对值 = 反码按位取反 = 0000 0010 = 2 ,所以结果是-2
即 a = -2,b = 127
两种方法的区别:
1.start方法
用 start方法来启动线程,是真正实现了多线程, 通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法。但要注意的是,此时无需等待run()方法执行完毕,即可继续执行下面的代码。所以run()方法并没有实现多线程。
2.run方法
run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码。
枚举类有多少个实例,就会调用多少次构造方法
枚举类构造方法只能加private修饰符(或不加),因为枚举类本身已经是构造好的,不允许再被外部构造
选B。考察的是类所包含的类型变量。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理
CMS收集器,基于标记清理
G1收集器:整体上是基于标记 整理 ,局部采用复制
综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。
异常分为运行时异常,非运行时异常和error,其中error是系统异常,只能重启系统解决。非运行时异常需要我们自己补获,而运行异常是程序运行时由虚拟机帮助我们补获,运行时异常包括数组的溢出,内存的溢出空指针,分母为0等!
运行时异常
ClassCastException(类转换异常)
ClassNotFoundException
IndexOutOfBoundsException(数组越界异常)
NullPointerException(空指针异常)
非运行时异常
IOException
SqlException
ArrayStoreException(数组存储异常,即数组存储类型不一致)
还有IO操作的BufferOverflowException异常
该代码段能编译通过并正常运行
因为Test类的hello方法是静态的,所以是属于类的,当实例化该类的时候,静态会被优先加载而且只加载一次,所以不受实例化new Test();影响,只要是使用到了Test类,都会加载静态hello方法!
另外,在其他类的静态方法中也是可以调用公开的静态方法,此题hello方法是使用public修饰的所以在MyApplication中调用hello也是可以的。
总结:即使Test test=null;这里也会加载静态方法,所以test数据中包含Test类的初始化数据。(静态的,构造的,成员属性)
因此test.hello是会调用到hello方法的。
属于被动引用不会出发子类初始化
1.子类引用父类的静态字段,只会触发子类的加载、父类的初始化,不会导致子类初始化
2.通过数组定义来引用类,不会触发此类的初始化
3.常量在编译阶段会进行常量优化,将常量存入调用类的常量池中, 本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
所以答案是
P is init
123
普通的java对象是通过new关键字把对应类的字节码文件加载到内存,然后创建该对象的。
反射是通过一个名为Class的特殊类,用Class.forName("className");得到类的字节码对象,然后用newInstance()方法在虚拟机内部构造这个对象(针对无参构造函数)。
也就是说反射机制让我们可以先拿到java类对应的字节码对象,然后动态的进行任何可能的操作,
包括
这些都是反射的功能。
使用反射的主要作用是方便程序的扩展。
当一个类或接口被加载到JVM的时候便会产生一个与之关联的一个Java.lang.Class对象,我们可以通过此Class对象来得到被装入的类的详细信息。
其中:
Method[] getDeclaredMethods() 返回 Class 对象表示的类或接口的所有已声明的方法数组,但是不包括从父类继承和接口实现的方法。
Method[] getMethods() 返回当前 Class 对象表示的类或接口的所有公有成员方法对象数组,包括已声明的和从父类继承或实现接口的方法。
A 显然是错误的,Java一律采用Unicode编码方式,每个字符无论中文还是英文字符都占用2个字节。
B 也是不正确的,不同的编码之间是可以转换的,通常流程如下:
将字符串S以其自身编码方式分解为字节数组,再将字节数组以你想要输出的编码方式重新编码为字符串。
例:String newUTF8Str = new String(oldGBKStr.getBytes("GBK"), "UTF8");
C 是正确的。Java虚拟机中通常使用UTF-16的方式保存一个字符(Java的class文件编码为UTF-8,而虚拟机JVM编码为UTF-16)
D 也是正确的。ResourceBundle能够依据Local的不同,选择性的读取与Local对应后缀的properties文件,以达到国际化的目的。
综上:答案是C、D
该段程序会抛异常,原因如下:
对于集合的三种遍历方式删除:
1.普通for循环:可以删除
注意每次删除之后索引要--
2.Iterator遍历:可以删除
不过要使用Iterator类中的remove方法,如果用List中的remove方法会报错
3.增强for循环foreach:不能删除
强制用List中的remove方法会报错