一、Java的八大数据类型:
bit为字节,byte为位。
整数:
byte:8位 最大存储数据量是255, 存储范围是在-128~127之间
short:16位 最大的存储数据量是65536,存储范围是在-32768~32767之间。
int:32位 最大的存储数据量是2的32次方减1,存储范围是在负的2的31次方 到正的2的31次方减1
long:64位 最大的存储数据量是2的64次方减1,存储范围是在负的2的63次方到正的2的63次方减1
字符:
char:16位,存储量是Unicode码,以单引号赋值
双精精度:
double:64位,数据范围在4.9e-324~1.8e308,使用时后缀的d或D可加可不加。
单精度:
float:32位,数据范围在3.4e-45~1.4e38,使用时后缀必须加上f或F,如果不加则默认是-double类型
布尔值:
boolean:只有两个取值true和false
Java提供的这些数据类型的大小,并不是随着机器的结构的变化而变化,这种数据类型的大小的不可更改是因为Java的很强的移值能力的原因之一。
八大基本数据类型的包装类:
byte---------Byte,short-----------Short,int-----Integer,long----------Long,
char-----Character
boolean-----Boolean
double--------Double,float-------Float
注:String是包装类,即是对象,并不是基本数据类型。
注:Java的基本数据类型存储在栈中,Java的基本类型的包装类存储在堆中,相较包装类,基本数据类型的存取速度要快些。
Java jdk5.0开始,虚拟机就实现了基本数据类型与包装类之间的自动装换。
基本类型的优势:数据存储相对简单,运算效率比较高
包装类的优势:有的容易,比如集合的元素必须是对象类型,满足了java一切皆是对象的思想
数据类型间的转换:
简单的数据类型的转换有以下两种:自动转换跟强制转换。
自动转换:以具体的讲就是当一个大的数据与一个小的数据进行运算时,系统会自动将小的数据转换成大的数据格式,再进行运算。而这些数据的大小如下:byte,short,char,int,long,float,double。它们的大小不是取决于字位的大小,而是取决于存储范围的大小。
byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换。
强制转换:
就是大数据值转换为小数据值,这就要用到强制转换,但是数据大转换为小时会丢失精度。
表达式的数据类型自动提升, 关于类型的自动提升,注意下面的规则:
①所有的byte,short,char型的值将被提升为int型;char转换为int型时,会根据ascll编码对应的数值。
②如果有一个操作数是long型,计算结果是long型;
③如果有一个操作数是float型,计算结果是float型;
④如果有一个操作数是double型,计算结果是double型;
面向对象:
Java的面向对象有三大特征:继承,封装,多态。
概述:
什么是继承?
继承就是将共有的属性,方法提取出来,放到一个类中,而该类就是父类,超类,基类。子类通过关键字extends来继承该类,实现该超类的方法。注意该超类是抽象类,抽象类中可以有构造方法,可以没有抽象方法,但有抽象方法的类就一定是抽象类。子类在继承超类时,必须要实现该超类定义的方法,如果没有实现该超类的方法,那么该子类就要是抽象类,超类的构造方法不可以被子类继承,但可以被子类访问,超类的私有修饰的属性或方法不能被子类继承。
继承的好处:提高了Java程序的代码的复用性
什么是封装?
封装顾名思义就是将东西包装起来,这里的封装是将程序的代码属性跟方法,类进行包装。封装给程序的代码提高了安全性,
防止该类的代码和数据被外部类定义的代码随机访问,而要访问该类的代码和数据,则需要通过特定的方法才能进行访问。
什么是多态?
同一种操作作用于不同的类对象,实现不同的效果。
有两个好处:
1. 应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。//继承
2. 派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。 //多态的真正作用,
接口和抽象类的区别:
比较点 | 抽象类 | 接口 |
默认方法 | 抽象类可以有默认的实现方法 | jdk8之前接口是不能实现方法的 |
实现方法 | 子类通过extends关键字类继承该抽象类,如果子类不是抽象类,那么子类就必须要实现该抽象类定义的抽象方法 | 子类通过implements关键字来实现接口,子类必须实现接口的全部方法 |
构造器 | 抽象类中可以有构造方法 | 接口不可以有构造方法 |
和正常类的区别 | 抽象类不能被实例化 | 接口则是不同的类型 |
访问修饰符 | 抽象方法可以有public,protected和default等修饰 | 接口默认的是public修饰符,其他修饰符不可以 |
多继承 | 子类只能继承一个父类 | 多接口 |
添加新方法 | 抽象类中添加新方法,可以提供默认的实现方法,因此可以不必修改子类现有的代码 | 如果添加新方法,子类必须实现该方法 |
父类的静态方法能否被子类重写?
不能,重写只适用于实例方法,不能用于静态方法,而子类当中含有和父类相同签名的静态方法,我们称只为隐藏。
什么是不可变对象?好处是什么?
不可变对象指对象一旦被创建,状态就不可以被改变,任何的修改都会创建一个新的对象。
不可变对象的好处就是线程安全。
静态变量和实例变量的区别?
静态变量存储在方法区,属于类的所有,实例变量存储在堆当中,其应用存在当前的线程栈中,需要注意的是从JDK1.8开始用于实现方法区的PermSpace被MetaSpace取代了.
能否包含一个不可变对象的可变对象?
能,比如final Person[] persons = new Persion[]{}
.persons是不可变对象的引用,但其数组中的Person实例却是可变的.这种情况下需要特别谨慎,不要共享可变对象的引用.这种情况下,如果数据需要变化时,就返回原对象的一个拷贝.
Java创建对象的几种方法:
- new创建新对象
- 通过反射机制
- 采用clone机制
- 通过序列化机制
(1)、User user = new User(); 这就是通过new创建出来的对象,也叫实例化对象。
(2)、反射机制有三种获取对象方法
方法一:调用对象的getClass()方法
User user = new User();
Class cls = user.getClass();
方法二:通过类的class调用
Class cls = User.class();
方法三:通过class.forName方法
try{
Class cls = Class.forName("application.properties")
}catch(ClassNotFoundExcption e){
e.printStackTrace();
}
前两者都需要显式地调用构造方法. 对于clone机制,需要注意浅拷贝和深拷贝的区别,对于序列化机制需要明确其实现原理,在java中序列化可以通过实现Externalizable或者Serializable来实现.
switch中能否使用String做参数?
jdk1.7之前是不支持String做为参数的,只支持:byte,char,short,int这几个基本数据类型和其对应的封装类型
switch(参数){// 括号里是一个表达式,结果是个整数
case 1: // case 后面的标号,也是个整数
//选项值
break;
case 2:
//选项值
break;
default:
default group of statements
}
jdk1.7之后支持String,枚举,整形。但不支持long类型。
注:jdk1.7并没有新的指令来处理switch string,而是通过调用switch中string.hashCode,将string转换为int从而进行判断。
a==b与a.equals(b)的区别?
如果a和b都是对象的情况下,a==b比较的是堆中的内存地址,只有当两个对象都是指向同一个对象的堆地址时,才显示为true。
而a.equals(b)判断的是指向内存中的值是否相等。
如果a和b都是变量的情况下,a==b比较的是内存中的地址,而a.equals(b)判断的是指向内存中的值是否相等。
注:==指引用是否相同。 equals()指的是值是否相同。
public static void main(String[] args) {
String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
System.out.println(aa == bb); // true
System.out.println(a == b); // false,非同一对象
System.out.println(a.equals(b)); // true
System.out.println(42 == 42.0); // true
}
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = new Object();
System.out.println(obj1.equals(obj2));//false
System.out.println(obj1==obj2);//false
obj1=obj2;
System.out.println(obj1==obj2);//true
System.out.println(obj2==obj1);//true
&和&&的区别?
&是位操作,&&是逻辑运算符。逻辑运算符具有短路特性,&不具短路特性。
例如以下代码:
public static void main(String[] args) {
int i =1;
if (i==1 && i++==2){
System.out.println("true");
}else {
System.out.println("false"+i);
}
}
输出的是false2
&&逻辑运算当第一个条件判断为false时,就不执行后面的条件,直接输出结果。
&位操作当第一个条件判断为false时,还会继续执行后面的条件,再输出结果。
Object中的equals()和hashcode()的联系:
hashCode是Object中的一个方法,返回一个哈希值,如果两个对象根据equals()方法比较相等,那么调用这两个对象中任意一个对象的hashCode()方法必须产生相同的哈希值,如果两个对象根据equals()方法比较不相等,那么产生的哈希值不一定相等(碰撞的情况下还是会相等的)
a.hashCode()有什么用?与a.equals(b)有什么关系
hashCode()
方法是为对象产生整型的 hash 值,用作对象的唯一标识.它常用于基于 hash 的集合类,如 Hashtable,HashMap等等.根据 Java 规范,使用 equal()
方法来判断两个相等的对象,必须具有相同的 hashcode.
将对象放入到集合中时,首先判断要放入对象的hashcode是否已经在集合中存在,不存在则直接放入集合.如果hashcode相等,然后通过equal()
方法判断要放入对象与集合中的任意对象是否相等:如果equal()
判断不相等,直接将该元素放入集合中,否则不放入.
有没有可能两个不相等的对象有相同的hashcode
有可能.在产生hash冲突时,两个不相等的对象就会有相同的 hashcode 值.当hash冲突产生时,一般有以下几种方式来处理:
- 拉链法:每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表,被分配到同一个索引上的多个节点可以用这个单向链表进行存储.
- 开放定址法:一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入
- 再哈希:又叫双哈希法,有多个不同的Hash函数.当发生冲突时,使用第二个,第三个….等哈希函数计算地址,直到无冲突.
可以在hashcode中使用随机数字吗?
不行,因为同一对象的 hashcode 值必须是相同的.