(1)

原生类是指Java中,数据类型分为基本数据类型(或叫做原生类、内置类型)和引用数据类型。

那么原生类为基本数据类型,有八种,这样转换的时候就有表达范围问题。

1、所占位数少的可以转换为所占位数多的类型,比如byte转char,char转int等;

2、而所占位数多的转为所占位数少的默认情况下不能实现转换,需要强制类型转换,这样可能会丢失一部分原始数据;

3、此外,boolean类型数据和其他七种不能互相转换。

(2)以下代码执行后输出结果为( )


blockAblockBblockA


public class Test

{

public static Test t1 = new Test();

{

System.out.println("blockA");

}

static

{

System.out.println("blockB");

}

public static void main(String[] args)

{

Test t2 = new Test();

}

}

解析:

首先,需要明白类的加载顺序

(1) 父类静态对象和静态代码块

(2) 子类静态对象和静态代码块

(3) 父类非静态对象和非静态代码块

(4) 父类构造函数

(5) 子类 非静态对象和非静态代码块

(6) 子类构造函数

其中:类中静态块按照声明顺序执行,并且(1)和(2)不需要调用new类实例的时候就执行了(意思就是在类加载到方法区的时候执行的)
2.因而,整体的执行顺序为 

public static Test  t1 = new Test();         //(1)

static 
{
System.out.println("blockB");                //(2)

}

Test t2 =new Test();                             //(3)

在执行(1)时创建了一个Test对象,在这个过程中会执行非静态代码块和缺省的无参构造函数,在执行非静态代码块时就输出了blockA;然后执行(2)输出blockB;执行(3)的过程同样会执行非静态代码块和缺省的无参构造函数,在执行非静态代码块时输出blockA。

(3)

选A 只有静态方法才能被类名调用。

B、一般方法,只能被实例对象调用

C、final修饰方法,只是说明本方法不能被重写。

D、abstract修饰方法,表示本方法为抽象方法,没有方法体,且抽象方法必须在抽象类中,但是抽象类中可以没有抽象方法。

(4)下面的程序 编译运行后,在屏幕上显示的结果是 0

public class test {

public static void main(String args[]) {

int x,y;

x=5>>2;

y=x>>>2;

System.out.println(y);

}

}

解析:

5的二进制是0101。

x=5>>2 (>>带符号右移)

将0101右移2位,为:0001。

y=x>>>2 (>>>无符号右移,左边空缺补充为0)

将0001右移2位,补0。结果为:0000。

所以得出答案0

 

这道题首先要知道二进制的计算方式

举例:0011

二进制换算十进制,从右到左,以当前位数字 乘以 2 的索引字幂,然后相加,索引从0开始计算。

如:

右一数字为1,索引为0。所以为:1*2^0(1乘以2的0次方)

右二数字为1,索引为1。所以为:1*2^1(1乘以2的1次方)

右三数字为0,索引为2。所以为:0*2^2(0乘以2的2次方)

右四数字为0,索引为3。所以为:0*2^3(0乘以2的3次方)

最后把结果相加。所以计算方式为:

0*2^3+0*2^2+1*2^1+1*2^0

=0+0+2+1

=3

(5)

JVM

关于堆和栈

Java 把内存划分成两种:一种是栈内存,另一种是堆内存。

  • 栈式存储:
  • 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
  • 优点:存取速度比堆要快,仅次于寄存器,栈数据可以共享。
  • 缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。
  • 堆式存储:
  • 堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。
  • 优点:堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。
  • 缺点是:由于要在运行时动态分配内存,存取速度较慢。

jvm布局

  • 栈有两部分,Java线程栈以及本地方法栈。里面存放的都是栈帧,一个栈帧代表的就是一个函数的调用,在栈帧里面存放了函数的形参,函数的局部变量,返回地址等,在这个基本架构图中,可以看出JVM还定义了一个本地方法栈,本地方法栈是为Java调用本地方法【这些本地方法是由其他语言编写的】服务的。
  • JVM中栈有两个,但是堆只有一个,每一个线程都有自已的线程栈【线程栈的大小可以通过设置JVM的-xss参数进行配置,32位系统下,JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K】,线程栈里面的数据属于该线程私有,但是所有的线程都共享一个堆空间,堆中存放的是对象数据,什么是对象数据,排除法,排除基本类型以及引用类型以外的数据都将放在堆空间中。其中方法区和堆是所有线程共享的数据区。

本地方法栈

  • 在HotSpot虚拟机将本地方法栈和虚拟机栈合二为一,它们的区别在于,虚拟机栈为执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。

pc寄存器

  • 程序计数器,在CPU的寄存器中有一个PC寄存器,存放下一条指令地址,这里,虚拟机不使用CPU的程序计数器,自己在内存中设立一片区域来模拟CPU的程序计数器。只有一个程序计数器是不够的,当多个线程切换执行时,那就单个程序计数器就没办法了,虚拟机规范中指出,每一条线程都有一个独立的程序计数器。注意,Java虚拟机中的程序计数器指向正在执行的字节码地址,而不是下一条。

java栈

  • Java虚拟机栈也是线程私有的,虚拟机栈描述的是Java方法执行的内存模型:每个方法执行的时候都会创建一个栈帧,用于存放局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用直到执行完成的过程都对应着一个栈帧在虚拟机中的入栈到出栈的过程。我们平时把内存分为堆内存和栈内存,其中的栈内存就指的是虚拟机栈的局部变量表部分。局部变量表存放了编译期可以知道的基本数据类型(boolean、byte、char、short、int、float、long、double),对象引用(可能是一个指向对象起始地址的引用指针,也可能指向一个代表对象的句柄或者其他与此对象相关的位置),和返回后所指向的字节码的地址。其中64 位长度的long 和double 类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用1个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。当递归层次太深时,会引发java.lang.StackOverflowError,这是虚拟机栈抛出的异常。

  • Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。这个区域是用来存放对象实例的,几乎所有对象实例都会在这里分配内存。堆是Java垃圾收集器管理的主要区域(GC堆),垃圾收集器实现了对象的自动销毁。Java堆可以细分为:新生代和老年代;再细致一点的有Eden空间,From Survivor空间,ToSurvivor空间等。Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。可以通过-Xmx和-Xms控制

方法区

  • 方法区也叫永久代。在过去(自定义类加载器还不是很常见的时候),类大多是”static”的,很少被卸载或收集,因此被称为“永久的(Permanent)”。永久代也是各个线程共享的区域,它用于存储已经被虚拟机加载过的类信息,常量,静态变量(JDK7中被移到Java堆),即时编译期编译后的代码(类方法)等数据。从JDK7开始永久代的移除工作,贮存在永久代的一部分数据已经转移到了Java Heap或者是Native Heap。但永久代仍然存在于JDK7,并没有完全的移除:符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java heap;类的静态变量(class statics)转移到了java heap。随着JDK8的到来,JVM不再有PermGen。但类的元数据信息(metadata)还在,只不过不再是存储在连续的堆空间上,而是移动到叫做“Metaspace”的本地内存(Native memory)中。
    在JVM***享数据空间划分如下图所示
  • VM***享数据空间可以分成三个大区,新生代(Young Generation)、老年代(Old Generation)、永久代(Permanent Generation),其中JVM堆分为新生代和老年代
  • 新生代可以划分为三个区,Eden区(存放新生对象),两个幸存区(From Survivor和To Survivor)(存放每次垃圾回收后存活的对象)
  • 永久代管理class文件、静态对象、属性等
  • JVM垃圾回收机制采用“分代收集”:新生代采用复制算法,老年代采用标记清理算法。

(6)以下程序段的输出结果为:


false,true


public class EqualsMethod

{

public static void main(String[] args)

{

Integer n1 = new Integer(47);

Integer n2 = new Integer(47);

System.out.print(n1 == n2);

System.out.print(",");

System.out.println(n1 != n2);

}

}

解析:

使用Integer a = 1;或Integer a = Integer.valueOf(1); 在值介于-128至127直接时,作为基本类型。

使用Integer a = new Integer(1); 时,无论值是多少,都作为对象。

也就是说上面的实际上是不同的对象的,不能基本数据类型来进行运算

(7)下面哪段程序能够正确的实现了GBK编码字节流到UTF-8编码字节流的转换:byte[] src,dst;


dst=new String(src,"GBK").getBytes("UTF-8")


解析:

操作步骤就是先解码再编码

用new String(src,"GBK")解码得到字符串

用getBytes("UTF-8")得到UTF8编码字节数组

(8)没有<<<运算符

<<表示左移位

>>表示带符号右移位

>>>表示无符号右移

但是没有<<<运算符