一、Java的基本数据类型有哪些?
整数型: byte,short,int,long。
浮点型: float,double。
字符型: char。
逻辑型: boolean。
二、字符型char
1. 字符常量常用单引号括起来的单个字符,如char a='a'。
2. Java字符采用Unicode编码,每个字符占2个字节。因此可以用十六进制的编码形式表示。
char c1='\u00061';
3. Java语言中还允许使用'\'将其后的字符转变为其它的含义,如: char c1='\n'; c1表示换行符。
4. a对应的ascii码为97,A为65。
三、 整数类型
1. Java各整数类型有固定的表数范围和字段长度,不受操作系统的具体影响,以保证Java程序的可移植性。
2. Java整型常量的三种表现形式:
十进制: 12,0,-200;
八进制,要求以O开头,如: O12。
十六进制,要求以Ox开头,如Ox12。
3. Long类型的数据需要在后面添加L,否则会报错。
4. 字节范围:
byte 1字节,-128~127 ;
short 2字节,-2^15~2^15-1;
int 4字节,-2^31~2^31-1;
long 8字节:-2^63~2^63-1;
四、 浮点类型
1.浮点类型默认的是double类型,如果声明为float类型,那么需要在变量后面添加f,如 float a=1.2f;
2. float类型,4字节,小数点后7位,double 类型,8字节,小数点后15位,总结: 有效数字位数=整数位数+小数位数,7位以内的用float,15位以内的用double
3. 在使用float或者double进行计算时,会出现精度丢失,通常使用BigDecimal进行更为准确的精度运算。
五、基本数据类型的转换
1. boolean类型的变量不能转换为其他类型的数据。
2. 整型变量可以自动转换,在运算的时候的转换规则如下:
1) byte,short,char之间不会相互转换。
2) byte,short,char ->int ->long->float->double, 容量小的会自动向容量大的转换。如:
int a=1;
Long b=2L;
Long result=a*b; //运算时会将int类型的a转换为Long类型。
3. 大类型向小类型转换为出现精度丢失、类型溢出,另外float强制转换为Long类型时,会直接舍弃小数部分。
精度丢失:
Float和Double提供了快速的运算,但是这2种类型的数据做二进制转换的时候,有些数字不能完全转换,造成精度丢失。
float a1=1.2f;
double b1=2.5;
double c=a1*b1;
System.out.println(c);
打印结果:
3.0000001192092896
实际在开发中,我们对数据的要求较高的时候,那么尽量使用BigDecimal类型来定义小数。
类型溢出:
int a=1000000000;
int b=1000;
System.out.println(a*b);
打印结果: -727379968 乘算的结果明显超出了Int类型的最大值。
六、为什么新建对象的时候需要重写equals方法的同时又需要重写hashCode()方法?
答:
因为所有的类是Object的子类,每个类都会根据hash算法计算的哈希值来对应一个hashCode, 不同的类的对象可能会计算生成相同的hashCode。主要有以下情况:
1) 如果2个对象hashCode不相等,那么2个对象肯定是不相同,因为hashcode的计算具有幂等性。
2) 如果2个对象使用equals()方法相等,那么hascode的值一定相等,2个对象肯定相同。
3) 如果2个对象是hashCode()方法结果相等,那么equals()方法的结果有可能为true,也有可能会false,2个对象不一定相等,这种情况存在于哈希表里的相同位置下的链表处的不同位置。
七、 final关键字的用法
答: 修饰在类上该类不能被继承,修饰方法,在子类该父类的方法不能被重写, 修饰变量相当于是个常量,但不能被重新赋值, ,否则会报错。
八、访问控制和继承
答:需要牢记一点: 子类的访问权限需要大于或者等于父类。 明细规则如下: ;
- 父类中声明为 public 的方法在人类中也必须为 public。
- 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
- 父类中声明为 private 的方法,不能够被继承。
九、 抽象类有哪些特性?
答:
1. 抽象类里的抽象方法必须使用Public或者protected访问权限来控制,不能使用private。
2. 抽象类可以含有构造方法,因为抽象类可以使用匿名内部来实例化。
3. 抽象类与具体的类不同点在于,抽象类可以包含抽象方法,由其子类去具体的实现抽象方法,而且抽象类需要使用abstract 来进行修饰。
例如:
package com.example.traditional;
/**
*author:bingbing
*日期:2020年7月13日
*时间:下午10:06:41
*/
public abstract class Pizza {
protected String name;
public abstract void method();
Pizza(){
System.out.println("实例化抽象类!");
}
}
在Main方法里可以这样,只需要在匿名名内部类的形式来实现定义的抽象方法即可。
package com.example.traditional;
/**
*author:bingbing
*日期:2020年7月13日
*时间:下午10:10:24
*/
public class Demo01 {
public static void main(String[] args) {
Pizza pizza=new Pizza() {
@Override
public void method() {
// TODO Auto-generated method stub
}
};
}
}
十、静态内部类有哪些特性?
1.静态内部类可以在外部类的静态成员中访问或者实例化(非静态内部类不可以)---优势,例如单例模式的实例化。
//使用静态内部类来创建实例
class Singleton {
private static volatile Singleton instance;
//私有构造器,防止被外部实例化
private Singleton() {}
//静态内部类,该类内有一个私有的静态属性
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
//提供一个公有的方法返回静态内部类创建的对象
public static synchronized Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
2.静态内部类可以访问外部类的静态成员不可以访问非静态成员(非静态内部类可以访问类的静态和非静态成员)---限制
需要在a变量修改成static 才行,由此可以发现静态内部类只能访问外部类的静态成员属性和方法。
3. 静态内部类可以申明静态成员(非静态内部类则不可以申明静态成员)
package com.example.thread;
public class Demo04 {
private static Demo04 demo04;
static int a=0;
static class Test{
Demo04 demo04=new Demo04();
static int b=1;
void test(){
a=5;
}
}
}
4.在外部类外创建该外部类的内部静态类,不用依附于外部类的实例(而非静态内部类则需要依赖于外部类的实例),即访问的时候直接使用外部类.静态内部类类名 ,非静态内部类需要new一个实例出来,才能够访问。
十一、接口有哪些特性?
答:
1) 接口支持多继承。
2) 接口声明的方法一般是没有body的,默认为public修饰,不能使用private和protected修饰。
3) jdk1.8后,可以在接口里写入含有body的方法,但需要使用default 关键字修饰。
4) 接口不能继承实体和抽象类。
public interface Test implements A,B,C{
public int test1();
class a{
}
default int test(){
return 0;
}
}
十二、值传递和引用传递
答案: A C D 考查的是引用传递和值传递,值传递是指在会将实参的变量进行拷贝一份,不会影响到实参的内容,引用传递的形参和实参实际指向的是内存中的同一个地址,但是参数地址不同,因此引用传递改变内容的话,也会改变实参的内容。
以下i的打印结果为:
package com.tedu.day05;
/**
*author:bingbing
*日期:2020年7月15日
*时间:下午9:36:06
*/
public class Demo01 {
public static void main(String[] args) {
int i=0;
aow(i++);
System.out.println(i);
}
private static void aow(int i) {
i+=2;
}
}
打印结果为: 1
考查值传递, 因为 aow方法的Int i为一个新的类型的Int,传参传的变量的一个拷贝,因此实际上i的值并没有发生改变。
十三、String 类型的学习
1. String str=new String("abc") ,创建了几个对象?
答: 1个或者2个,为什么是1个或者2个对象,那么我们可以先了解一下常量池的概念,JVM中 通过常量池来使字符串共享,那么使用常量池,可以避免字符串对象重复创建,比如常量池里面已经有了"abc", 那么String a="abc",就直接从常量池取出来。
分析: String str=new String("abc"); 可以将这一行代码拆分为"abc"和new String(),String类的构造方法同时也是一个String 类型的数据, String original也为一个字符串,如果常量池里没有这个字符串,因此会先在常量池里创建一个对象, 同时也会通过new来新建一个对象,此情况下是创建了2个对象。
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
如果常量池里已经存在了该字符串,那么就不会重复创建该对象,直接通过new来创建了一个对象。
2. String,StringBuilder,StringBuffer有什么区别?
String 是一个final类型,对值的修改是创建一个新的对象,如果常量池中存在,那么就不用重新创建,如果不存在那么就用重新创建对象,StringBuilder和StringBuffer对对象的修改可以多次,但不会创建新的对象。StringBuilder相比StringBuffer速度快,因为StringBuffer是线程安全的。
十四、 ==和equals的区别?
基本类型用==比较的时候,比较的是值的内容,如果是引用类型比较的是地址。
equals方法是Object类里的方法,用于比较地址,String类型重写了equals方法,比较的是内容值,包装类也重写了equals方法比较的也是值的内容。
object:
public boolean equals(Object obj) {
return (this == obj);
}
String:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
十五、重载、重写、向上造型、向下造型?
答:
重载在一个类里面,方法名相同,方法的参数不同,返回类型可相同也可不同。
重写在不同的类里面发生,子类重写父类的方法,调用的时候还是子类重写的方法。
向上造型,指子类的对象赋值给父类的引用。
向下造型,把指向子类对象的父类引用赋值给子类引用叫向下造型。
十六、什么是多态?
答:
1. 多态是指同一个行为具有多个不同的表现形式或形态,多态其实就是用同一个接口去实现不同的目的,如打印机:
2. 多态存在的条件是什么?
继承、重写、父类引用指向子类对象。
看如下例子:
package com.example.day06;
/**
*author:bingbing
*日期:2020年7月19日
*时间:上午10:33:25
*/
public abstract class Animal {
abstract void eat();
}
猫:
package com.example.day06;
/**
*author:bingbing
*日期:2020年7月19日
*时间:上午10:34:25
*/
public class Cat extends Animal {
@Override
void eat() {
System.out.println("猫吃鱼!");
}
}
狗:
package com.example.day06;
/**
*author:bingbing
*日期:2020年7月19日
*时间:上午10:34:02
*/
public class Dog extends Animal{
@Override
void eat() {
System.out.println("狗吃骨头");
}
}
测试类:
Cat 和Dog都是Animal的实例,因此可以使用intanceof 作判断:
package com.example.day06;
/**
*author:bingbing
*日期:2020年7月19日
*时间:上午10:35:21
*/
public class Test {
public static void main(String[] args) {
Cat c1=new Cat();
show(c1);
Dog d1=new Dog();
show(d1);
}
public static void show(Animal a) {
if(a instanceof Cat) {
Cat c=(Cat)a;
c.eat();
}else if(a instanceof Dog) {
Dog d=(Dog)a;
d.eat();
}
}
}
打印结果:
猫吃鱼!
狗吃骨头
十七、静态绑定和动态绑定的区别是什么?
答: 在java中,除了final、static、private修饰的方法和构造方法是静态绑定, 其他方式的方法均为动态绑定,在运行阶段绑定。区别有静态绑定是在编译阶段进行的,动态绑定是在运行阶段绑定的。
如下代码输出结果为:
public class Main {
public static void main(String[] args) {
Father father = new Son();
System.out.println(father.age);
father.name();
father.age();
}
}
class Father{
public int age = 50;
public static void name(){
System.out.println("Father name");
}
public void age(){
System.out.println("Father age is " + age);
}
}
class Son extends Father{
public int age = 20;
public static void name(){
System.out.println("Son name");
}
@Override
public void age(){
System.out.println("Son age is " + age);
}
}
打印结果:
50
Father name
Son age is 20
可以发现只有重写了的是动态绑定的,static修饰的方法时静态绑定的, fater.name() 方法仍然调用的是father的。