Java基础
1.Java语言有哪些特点?
- 简单易学
- 面向对象(封装、继承、多态)
- 平台无关性(Java虚拟机实现平台无关性)
- 可靠性、安全性
- 支持多线程(C++ 语言没有内置的多线程机制因此必须调用操作系统的多线程功能来进行多线程程序设计,而Java语言却提供了多线程支持)
- 支持网络编程并且很方便 (Java语言诞生本身就是为了简化网络编程设计的,因此Java语言不仅支持网络编程并且很方便)
- 编译与解释并存
2.字节码是什么?有什么好处?
- JVM可以理解的代码叫做字节码,即class文件,他不面向任何指定的处理器,只面向虚拟机
- 一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点
3.Java和C++的区别
- 都是面向对象的语言,都支持封装、继承和多态
- Java不提供指针来访问内存,程序内存更加安全
- Java的类是单继承的,C++支持多继承;虽然Java的类不可以多继承,但是接口可以多继承
- Java有自动内存管理垃圾回收机制(GC),不需要程序员手动释放无用内存
- 在C语言中,字符串或字符数组最有都有一个额外的字符'/0'来表示结束。但是Java语言中没有这个概念
4.什么是Java程序的主类
一个程序可以有多个类,但是只能有一个主类,Java中是包含main方法的类,这是Java程序执行的入口
5.为什么说Java语言编译与解释并存
- 编译型语言:编译器针对特定的操作系统将源代码一次性翻译成可被该平台执行的机器码
- 解释型语言:解释器对源程序逐行解释成特定平台的机器码并立即执行
- 因为Java程序需要经过先编译,后解释两个步骤,由Java编写的程序需要先经过编译步骤,生成字节码(.class文件)
- 这种字节码必须由Java解释器来解释执行。因此,我们可认为Java语言编译解释并存
6.字符常量和字符串常量的区别
- 形式上:字符单引号 字符串双引号
- 含义上:字符可视为整型值,字符串代表一个地址值,其字符串内容存储在内存常量池中
- 占内存大小 字符2个字节 字符串不一定
7.八种基本数据类型
| 基本类型 | 位数 | 字节 | 默认值 |
|---|---|---|---|
| int | 32 | 4 | 0 |
| short | 16 | 2 | 0 |
| long | 64 | 8 | 0l |
| byte | 8 | 1 | 0 |
| char | 16 | 2 | ‘u0000’ |
| float | 32 | 4 | 0f |
| double | 64 | 8 | 0d |
| bollean | 1 | false |
8.Java泛型了解么?什么是类型擦除?介绍一下常用的通配符?
-
JDK5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说操作的数据类型被指定为一个参数
-
Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,这也就是通常所说的类型擦除
ArrayList<String> list1 = new ArrayList<String>();
list1.add("abc");
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(123);
System.out.println(list1.getClass() == list2.getClass()); //true
- 如在代码中定义List和List等类型,在编译后都会变成List,JVM看到的只是List,而由泛型附加的类型信息对JVM是看不到的
- C#选择的是“具现化式泛型”,是占位符,具体存在的
- 常用的通配符 T、E、K、V、?
- ?表示不确定的Java类型
- T(type)表示具体的一个java类型
- K V(key value)分别代表java键值中的 key , value
- E(element)代表 Elemen
- ? Extends T
- ? super T
- ==它的作用是判断两个对象的地址是否相等。即判断两个对象是不是同一个对象
- equals的作用是判断两个对象是否相等,它不能用于比较基本数据类型的变量;String类中重写了equals方法,比较的是对象内容是否相等
- 默认的equals方法等价于==方法,因为Object中定义了equals方法,因此所有的Java类都实现了equals()方法,一般我们都会重写
- hashCode()与equals()都存在于Object类,因此所有类都会有这两个方法
- 创建类“散列表”,如:HashSet HashTable HashMap, 这时hashcode才有用,用于确定对象的位置:不是散列表就没用
- 两个对象相等,哈希码一定相同
- 两个对象的哈希码相同,对象不一定相等;有可能存在不同对象,有相同哈希值,这叫做哈希冲突
- 如果只重写了equals方法,不重写hashcode方法,那么new出来的对象哈希值都是不相同的,这样就可能存在两个对象内容相同,但是哈希码不同的情况,这是不符合定义的
- 除此之外,还能提高效率;重写hashcode,如果hashcode不同,那就不需要比较equals了,减少了equals的比较次数
- 装箱:将基本数据类型用它们对应的引用类型包装起来
- 拆箱:将包装类型转换为基本数据类型
- 实现过程:装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的xxxValue方法实现的
- 对于Integer:通过valueOf 创建Integer 对象的时候,如果数值在[-128,127]之间, 便返回指向IntegerCache.cache 缓存中已经存在的对象引用,否则创建一个新的Integer 对象
- 对于Double:通过valueOf 创建的Double 对象,都是新的对象new double(),无论
数值是多少,两个对象都不相等,但是equal 会是相同的
- Integer、Short、Byte、Character、Long 这几个类的valueOf 方法的实现是类似 的
- Double、Float 的valueOf 方法的实现是类似的
- Byte、Short、Integer、Long 都实现了常量池,默认创建了[-128,127]的数据缓存 类型,Character[0,127],Boolean 直接返回true 或者false
- 为什么设置为[-128,127]的区间?一是因为JAVA 技术规范的定义;而是性能和 资源之间的平衡
- Dobule 和Float 没有实现常量池技术,是直接创建新对象(即使两个对象的值相 同)
9.==和equals的区别
10.hashCode()与equals(),为什么重写equals时必须重写hashCode方法?
11.自动装箱与自动拆箱
12.为什么java中只有值的传递
按值传递:方法得到的所有参数值的一个拷贝,也就是说,方法不能修改传递给它的任何参数变量的内容
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student s1 = new Student("小张");
Student s2 = new Student("小李");
Test.swap(s1, s2);
System.out.println("s1:" + s1.getName());
System.out.println("s2:" + s2.getName());
}
public static void swap(Student x, Student y) {
Student temp = x;
x = y;
y = temp;
System.out.println("x:" + x.getName());
System.out.println("y:" + y.getName());
}
}
13.重载和重写的区别
- 同一个类中的多个同名方法,根据传进参数不同来决定执行处理;比如类的构造方法,多个构造方法的可能类型、个数都不同
- 重写就是当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法
- 返回值类型、方法名,参数列表必须相同,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类
- 如果父类访问修饰符为private/final/static则子类就不能重写该方法,但是被static修饰的方法能够被再次声明
- 构造方法无法被重写
- 方法的重写要遵循“两同两小一大”
- “两同”即方法名相同、形参列表相同;
- “两小”指子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声 明抛出的异常类应比父类方法声明抛出的异常类更小或相等;
- “一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。
14.深拷贝和浅拷贝
- 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝
- 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为什么拷贝
15.方法的四种类型
- 有参数有返回值
- 有参数无返回值
- 无参数有返回值
- 无参数无返回值
16面向过程和面向对象
- 面向过程:因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发
- 面向对象:易维护、易复用、易扩展。因为面向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护
17成员变量和局部变量的区别
- 从语法形式上看:成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或是方法的参数;成员变量可以被public,private,static 等修饰符所修饰,而局部变量不能 被访问控制修饰符及static 所修饰;但是,成员变量和局部变量都能被final 所修饰。
- 从变量在内存中的存储方式来看:如果成员变量是使用static 修饰的,那么这个成员变量是属于类的,如果没有使用static 修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。
- 从变量在内存中的生存时间上看:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
- 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外:被final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。(这在JVM 类加载 过程和对象创建过程有讲解)
18.对象如何创建的?对象实例和对象引用的关系
-
对象创建的过程在JVM,用new关键字
-
关系:对象引用指向对象实例;
Person b=new Person("a");new Person();是一个对象,放在堆(heap)空间。
a属于new Person()里面的是一个实例(放在常量池中)。
b属于一个引用,放在栈(stack)空间,要操作对象必须通过引用间接操作。
这个地址是指向new Person()这个对象的。
19 构造方法的作用、特性?在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
- 完成类的初始化工作
- 特性:名字与类名相同;没有返回值;生成类的对象自动执行,无需调用
- 帮助子类做初始化工作
20 面向对象的四大特征
- 抽象:将一类对象的共同特征总结出来构造类的过程,抽象只关注对象有哪些属性 和行为,并不关注它们的细节
- 封装:将一系列的信息全部包裹在方法中,其内部对外部不可见,外部程序只需要 调用接口API 即可实现功能,这样就省去了复杂代码
- 继承:类与类的一种关系,比如猫继承自动物,一般上层类都比较抽象,下层类都 是具体的,继承之后子类具有父类的所有方法和属性,private 除外
- 多态:对象的多种形态,即一个父类引用可以指向其本类的对象,也可以指向其子
类的对象
- 指向子类对象时,调用的方法为子类中继承的或者重写的方法
- 父类和子类之间支持向上/向下转型,但是不允许再添加第三方子类加入转 型
- 无论转型为父类引用还是子类引用,调用的都是子类中继承或重写的方法
- 父类不能调用子类特有的新方法,但是向下转型为子类引用后,可以调用子 类特有的新方法
- 优点:把不同子类都当做父类来看待,可以屏蔽子类之间的差异,写出通用代码, 适应变化
- 指向子类对象时,调用的方法为子类中继承的或者重写的方法
21 静态方法和实例方法的异同
- 静态方法可以使用类.方法名或者对象.方法名的方式调用;实例方法只能对象.方法名
- 无论new 了多少个对象,一个类都只有同一个静态方法
- 静态方法只能访问类中的静态成员(即静态方法和静态成员变量),不允许访问实例 方法和实例成员变量;而实例方法则没有这一限制
22 String StringBuffer 和StringBuilder 的区别是什么? String 为什么是不可变的?
- String 使用final 关键字来保存字符串,所以不可变
- StringBuilder 与StringBuffer 都继承自AbstractStringBuilder 类,没有final 修饰符 保存,所以是可变的
- String 中的对象不可变,所以是线程安全的
- AbstractStringBuilder 有许多公共方法;StringBuffer 对方法加了同步锁,所以是线程 安全的;但是StringBuilder 没有加同步锁,所以线程不安全
- 相同情况下使用StringBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的 性能提升,但却要冒多线程不安全的风险
- 适用情况:
- 操作少量的数据: 适用String
- 单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder
- 多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer
23 键盘输入的两种方法
- Scanner input = new Scanner(System.in);
- BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
24 反射机制
- 概念:在运行状态中,对任意一个类都能知道它的所有属性和方法;对任意一个对 象都能调用它的属性和方法;即动态获取信息和动态调用对象
- 优缺点:动态加载,提高代码灵活度;但性能慢,同时动态操作也增加了代码安全 隐患
25 异常
- 所有的异常都有一个共同的祖先java.lang 包中的Throwable 类。Throwable 类有两个重要的子类 Exception(异常)和 Erro(r 错误)。Exception 能被程序本身处理(try-catch),Error 是无法处理的(只能尽量避免)。
- Exception:catch 捕获异常,可以分为受检异常(必须处理)和非受检异常(可以不
处理)
- 受检异常:必须捕获或声明抛出这种异常(意外到达文件末尾、文件未找到)
- 非受检异常:runtimeException,如果不捕获异常,不会产生编译错误,异常在 运行时刻才会被抛出(算数运算出错、索引越界、数组索引)
- try……catch……finally:finally 语句都会被执行,finally 中return 返回语句优先级最高
- Error:程序无法处理,发生时,JVM 一般选择线程终止
26 多线程
-
线程:一个进程包含多个线程,同类的多个线程共享同一块内存空间和一组系统资 源,所以多线程切换工作时,负担比进程要小很多
-
进程:系统运行程序的基本单位
-
线程的6 个状态:
状态名称 说明 NEW 初始状态,线程被构建,但是还没有调用start()方法 RUNNABLE 运行状态,Java线程将操作系统中的就绪和运行两种状态笼统地称作“运行中” BLOCKED 阻塞状态,表示线程阻塞于锁 WAITING 等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通讯或中断) TIME_WAITING 超时等待状态,该状态不同于WAITING,它是可以在指定的时间自行返回的 TERMINATED 终止状态,表示当前线程已经执行完毕
27 文件与IO流
- 既然有了字节流,为什么还要字符流?
- 不管是文件读写还是网络发送接收,信息的最小存储单元都是字节,那为什么I/O 流操
作要分为字节流操作和字符流操作呢
- 字符流是由Java 虚拟机将字节转换得到的,问题就出在这个过程还算是非常耗时,并且,如果我们不知道编码类型就很容易出现乱码问题。所以, I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好