问题及答案来源自《Java程序员面试笔试宝典》第四章 Java基础知识 4.4基本类型与运算

1、Java提供了哪些基本数据类型?

Java一共提高了八种原始的数据类型:byte、short、int、long、float、double、char、boolean

基本数据类型不是对象,而是基本数据类型,这些数据类型变量在声明之后就会立刻在栈上被分配内存空间

八种基本类型可以分为以下四类:

  • int相关:short(2字节)、int(4字节)、long(8字节)
  • float相关:float(4字节)、double(8字节)
  • boolean相关:boolean(1字节)、byte(1字节)
  • char相关:char(2字节)(unicode字符)

另外Java还提供了对这些原始数据类型的封装类(字符类型Character、布尔类型Boolean、数值类型Byte、Short、

Integer、Long、Float、Double)

封装类型和原始类型的不同之处:

  • 原始类型传递参数按值传递,封装类型传递参数传的是引用
  • 类实例化时,封装类型默认值是null,原始类型默认值与它们的类型有关(比如int默认值为0)

精度损失:

当把高精度的变量赋值给低精度的变量时会造成精度损失,例如将double类型的数值赋值给float类型的变量

eg:float f = 0.93; 这样会造成精度损失,正确的方法是采用强制类型转换,eg:float f = (float)0.93;

2、什么是不可变类?

不可变类:

不可变类是指当创建了这个类的实例后,就不允许修改它的值,不可变类类似于常量,即只允许别的程序读,

但是不允许别的程序进行修改

常见的不可变类:

基本类型的封装类(Integer、Float等)、String

String类是不可变类,那么下面这段代码为什么可行?

 String s = "Hello";
s += " World";
System.out.println(s);

解释:

第2行代码中修改的只是s的引用,s由原来的指向"Hello"改成指向"Hello World",

原来的"Hello"还存在于内存中并没有被改变

3、值传递与引用传递有哪些区别?

Java语言中参数传递有两种方式:值传递和引用传递

值传递:

在方法调用中,实参把值传递给形参,形参只是用实参的值初始化一个临时的存储单元,因此形参与

实参虽然值一样,但是有着不同的存储单元,对形参的改变不会影响实参的改变

引用传递:

在方法调用中,传递的是对象(也可以看作是对象的地址),这是形参和实参的对象指向同一块存储单元,

因此对形参的修改就会影响实参的值

在Java中,原始数据类型在传递参数时按值传递,而普通对象在传递参数时按引用传递

实例如下:

 public class test {
public static void testPassParameter(StringBuffer ss1, int n){
ss1.append(" World"); // 引用
n = 8; // 值
} public static void main(String[] args) {
int i = 1;
StringBuffer s1 = new StringBuffer("Hello");
testPassParameter(s1, i);
System.out.println(s1); // Hello World
System.out.println(i); //
}
}

Java中八种基本数据类型都是按值传递,其他所有类型都是按引用传递,由于Java中八种基本数据类型的包装类型

都是不可变类型,因此增加了对按引用传递的理解难度,详细情况看下面的实例:

 public class test {
public static void changeStringBuffer(StringBuffer ss1, StringBuffer ss2) {
ss1.append(" World");
ss2 = ss1;
} public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = a;
b = new Integer(b.intValue() + 1);
System.out.println(a + " " + b); // 1 2 第10行代码实际上是创建了一个新的Integer对象
StringBuffer s1 = new StringBuffer("Hello");
StringBuffer s2 = new StringBuffer("Hello");
changeStringBuffer(s1, s2);
System.out.println(s1 + " " + s2); // Hello World Hello
}
}

由上面的实例可以看出,按引用传递实际上当修改形参中地址对应的内容时,实参会发生相应变化,但是当

直接改变形参地址时实参不会改变,这说明了按引用传递实际上也是一种按值传递(传的是地址)

也就是说引用传递不会改变实际参数指向的地址,但是能改变实际参数指向的地址中的内容

4、不同数据类型的转换有哪些规则?

背景描述:

在Java中,当参与运算的两个变量的数据类型不同时,就需要进行隐式的数据转换,规则为从低精度向高精度转换,

即优先级满足:byte < short < char < long < float < double,例如不同数据类型的值在进行运算时,short类型数据

能够自动转换成int类型,int类型能够自动转换成float类型等,反之则需要通过强类型转换

类型自动转换:

低级数据类型可以自动转换为高级数据类型,转换规则如下:

自动转换的注意事项:

  • char类型转换时会自动转换成其对应的ASCII码
  • byte、char、short类型的数据在参与运算时会自动转换成int型,但使用+=运算时不会产生类型转换
  • boolean类型是不能和其他数据类型相互转换的

强制类型转换:

当需要从高级数据类型转换成低级数据类型时,就需要进行强制类型转换,强制类型转换如下:

  • byte =》char
  • char =》byte
  • short =》byte、char
  • int =》byte、short、char
  • long =》byte、short、char、int
  • float =》byte、short、char、int、long
  • double =》byte、short、char、int、long、float

另外要注意进行强制类型转换可能会损失精度(高精度转换成低精度)

5、强制类型转换的注意事项有哪些?

Java中的+=是Java中规定的运算法,Java编译器会对其进行特殊处理,因此语句short s1 = 1; s1 += 1; 能够编译通过 

6、运算符优先级是什么?

7、Math类中round、ceil和floor方法的功能各是什么?

  • round:对数四舍五入
  • ceil:对数向上取整
  • floor:对数向下取整

下面是测试代码:

 public class test {
public static void main(String[] args) {
float m = 6.4f;
float n = -6.4f;
System.out.println(Math.round(m)); //
System.out.println(Math.round(n)); // -6
System.out.println("===============");
System.out.println(Math.ceil(m)); //7.0
System.out.println(Math.ceil(n)); // -6.0
System.out.println("===============");
System.out.println(Math.floor(m)); // 6.0
System.out.println(Math.floor(n)); // -7.0
System.out.println("===============");
}
}

8、++i和i++有什么区别?

在java的执行过程中,i++和++i都直接对i进行了i=i+1的操作,

但是不同的是i++得到的是i未进行加法操作的前的值的副本,而++i直接得到计算后的值

比如a = i++;是将i的值赋值给a然后i的值再+1,而a=++i是将i的值+1然后再将+1后的i的值赋值给a

示例代码:

 public class test {
public static void main(String[] args) {
int i = 1;
System.out.println((i++)+(i++)); //
System.out.println(i); //
System.out.println((i++)+(++i)); //
System.out.println(i); // 5
System.out.println((i++)+(i++)+(i++)); //
System.out.println(i); //
}
}

9、无符号数的右移操作 

Java提供了两种右移运算符:>>和>>>,>>被称为有符号右移运算符,>>>被称为无符号右移运算符

两者的区别:

  • >>在右移时,若参与运算的数为正数则在高位补0,若为负数则在高位补1
  • >>>则不同,不论参与运算的数字为正数或负数,均会在高位补0

引申 - <<运算符和>>运算符有什么异同?

<<运算符标识左移,左移n位表示原来的值乘2的n次方,经常用来代替乘法操作

例如,一个数m乘以16可以表示为将这个数左移4位(m<<4)

由于CPU直接支持位运算,因此位运算比乘法运算的效率更高

与右移运算不同的是左移运算没有有符号和无符号的区别,在左移时,移除高位的同时在低位补0

10、char型变量中是否可以存储一个中文汉字?

在Java中,默认使用unicode编码方式,即每个字符(char)占用两个字节,因此char可以存储中文汉字

String是由char组成的,但它采用了更灵活的方式存储,即英文占用一个字节,而中文一般占用两个字节

示例代码:

 public class test {
public static void getLen(String s){
System.out.println(s + "的长度是: " + s.length() + " 所占字节数是: " + s.getBytes().length);
} public static void main(String[] args) {
String s1 = "hello";
String s2 = "你好";
getLen(s1);
getLen(s2);
}
}

注:在Java中,中文字符所占的字节数取决于字符的编码方式,一般情况下,采用ISO8859-1编码方式时,

一个中文字符与一个英文字符一样只占1个字节;采用GB2312或GBK编码方式时,一个中文字符占2个字节;

而采用UTF-8编码方式时,一个中文字符会占3个字节

最新文章

  1. Linux堆溢出漏洞利用之unlink
  2. 使用reids结合wcf实现集群模式下的聊天室功能
  3. 10月16日下午MySQL数据库CRUD操作(增加、删除、修改、查询)
  4. Qt之键盘讲解
  5. java GUI,贷款服务器
  6. Android LogCat使用详解
  7. [cocos2d-js]按钮整合成大图后打APK后不显示
  8. CentOS 7 安装 mariaDB
  9. dubbo 服务化
  10. 【Vmware】VirtualBox下虚拟机的网络配置
  11. spring-session实现分布式集群session的共享
  12. Spring in action记录
  13. 深入分析Spring混合事务
  14. npm install 时出现的 EACCES: permission denied 错误的可能有效的解决方案
  15. &lt;算法图解&gt;读书笔记:第4章 快速排序
  16. ajax json struts JSP传递消息到action返回数据到JSP
  17. String类型的方法总结
  18. Linux内核分析(第五周)
  19. 转 sql 优化
  20. Python 中的 sys.argv 用法

热门文章

  1. Linux下你需要了解的10个网络和监控命令
  2. (1)变量、常量、程序交互、数据类型、bool、基本运算符
  3. (1)集合 ---遍历map集合
  4. Eclipse+Spring学习(一)环境搭建(转)
  5. MySQL--修改普通表为自增表
  6. MFC 对话框Picture Control(图片控件)中静态和动态显示Bmp图片
  7. docker 知识点
  8. IE浏览器从页面向后台Controller传中文值出现乱码问题
  9. Linux(Centos7)下安装 zookeeper docker版 集群
  10. 【jmeter】jMeter使用Badboy录制Web测试脚本