简单易学,有丰富的类库
面向对象(java最重要的特性,让程序耦合度更低,内聚性更高)
平台无关性(JVM是Java跨平台使用的根本)
可靠安全
支持多线程
面向过程:分析解决问题的步骤,然后用函数吧这些步骤一步一步的实现,然后在使用的时候一一调用则可。性能较高,所以单片机、嵌入式开发等一般采用面向过程开发
面向对象:吧构成问题的事物分解成各个对象,而建立对象的目的也不是为了完成一个个步骤,而是为了描述某个事物在解决整个问题的过程中所发生的行为。面向对象有封装、继承、多态的特性,所以易维护、易复用、易扩展。可以设计出低耦合的系统。但性能上,比面向过程低。
4.标识符的命名规则 标识符的含义:注:①int是基本数据类型,Integer是int的封装类,是引用类型。int默认值是0,而Integer默认值是null,所以Integer能区别出0和null的情况。一旦java看到null,就知道这个引用还没有指向某个对象,再任何引用使用前,必须为其指定一个对象,否则会报错。
②基本数据类型在声明时系统会自动给他分配空间,而引用类型声明时知识分配了引用空间,必须通过实例化开辟数据空间之后才可以赋值,数组对象也是一个引用对象,将一个数组赋值给另一个数组时,知识赋值了一个引用,所有通过某一个数组所做的修改在另一个数组中也看得见
虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译后都使用java虚拟机中的int数据类型替代,而boolean数组将会被编译成java虚拟机的byte数组,每个元素boolean元素占8位。这样我们可以得出boolean类型占了单独使用是4个字节,在数组中又是1个字节。使用int的原因是,对于当下32位处理器)CPU)来说,一次处理数据是32位(这里不是指32/64位系统,而是值CUP硬件层面),具有高效存取的特点
指在程序中,我们自定义的内容,譬如,类的名字,方法名称以及变量名称等,都是标识符
命名规则:
标识符可以包含英文字母大小写,0~9的数字,$ 以及 _
标识符规范:
类名规范:(大驼峰式)首字母大写,后面单词首字母大写
变量名规范:(小驼峰式)首字母小写,后面每个单词首字母大写
**方法名规范:**同变量名
5.instanceof 关键字使用instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例
用法: boolean result = obj instanceof Class
obj表示一个对象,Class表示一个类或接口,当obj为Class对象时,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回true,否则false。
6.Java自动装箱和拆箱注意:编译期会检查obj是否能扎转换为右边class类型,如果不能转换则直接报错,如果不能确定类型,则编译通过,具体看运行时定。
装箱:
自动将基本数据类型转换为包装类型(int–>Integer);调用方法:Integer的valueOf(int)
拆箱:
自动将包装类型转换为基本数据类型(Integer–>int);调用方法:Integer的intValue
7.重载和重写的区别重写(Override)
子类吧父类本身有的方法重新写一遍。(针对方法体)
发生在父类与子类之间
方法名,参数列表,返回类型(子类中方法的返回类型是父类中返回类型的子类)必须相同
访问修饰符的限制一定大于等于被重写方法的访问修饰符(public>protected>default>private)
重写法法一定不能抛出新的检查异常或者比被重写方法声明更加宽泛的检查型异常
重载(Overload)
在同一个类中。同名的方法如果有 不同的参数列表,则视为重载
是一个类中多态性的表现
要求同名方法的参数列表不同(参数类型、参数个数甚至参数顺序)
返回值类型没有要求
==
比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否为同一个对象。比较的是真正意义上的指针操作。
equals
重写后用来比较两个对象的内容是否相等。equals是Object中方法,没有进行重写,返回的是和==一样
java集合Set,是无无序不重复的。当我们在set中插入时,怎么判断是否已存在该元素,如果只只用equals方法,那么效率太低。
hashcode方法可以这样理解:它返回的就是根据对象对象的内存地址换算出的一个值,当集合添加元素时,先调用这个元素的hashCode方法,就能一下定位到它应该放置的物理位置上。如果这个位置没有元素,就不需要再进行比较了,如果这个位置有元素,则调用equals方法进行比较,相同的话就不存,不同的话就再寻找(hash碰撞)。
equals同,hashcode同;hashcod同,equals不一定同
10.String、StringBuffer、StringBuilder的区别是什么String是只读字符串,并不是基本数据类型而是一个对象。从底层源码来看是一个final类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改。每次对String的操作都会生成新的String对象。
private final char value[];
StringBuffer和StringBuilder都继承了AbstractStringBuilder抽象类,他们的底层都是可变的字符数组,所以在进行频繁的字符串操作,建议使用StringBuffer和StringBuilder。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder是非线程安全的。
char[] value;
运行速率上:StringBuilder>StringBuffer>String
11.ArrayList和LinkedList区别Array(数组):
基于索引的数据结构,它使用索引在数组中搜索和读取数据。Array获取数据的时间复杂度是O(1),但是删除数据开销很大,因为需要重排数组中的所有数据。数组初始化必须制定初始化长度。
List(集合):
有序集合,可以包含重复元素,提供了按索引访问的方式,继承了Collection,有两个重要的实现类:ArrayList和LinkedList。
**ArrayList:**可以看成自动增长容量的数组。删除和插入需要移动数据。所以修改数据效率没有LinkedList高
**LinkedList:**双链表,查询元素时效率低于ArrayList。链表不需要连续的空间,大小不确定。
12.HashMap和HashTable区别- 两者的父类不同:HaspMap继承自AbstractMap类,而HashTable继承自Dictionary类,但同时实现了map,Cloneable、Serializable这三个接口
- 对外提供的接口不同:HashMap比HashTable多提供了elements()和Contains()两个方法。
- 对null支持不同:HashTable的key和value都不能为null;HashMap的key可以为空(唯一),value可以多个为null
- 安全性:HashMap非线程安全的(ConcurrentHashMap线程安全,效率比HashTable高,采用的是分段锁);HashTable是线程安全的,可用于多线程。
- 初始容量不同和每次扩容大小不同:HashMap初始容量为16,扩容是翻倍+1;HashTable初始容量是11,扩容是翻倍。
- 计算hash值的方法不同:HashTable是采用key的hashCode(),而HashMap重新计算key的hash值
Collection是集合类的上级接口,子接口有Set、List、LinkedList、ArrayList、Vector…
Collections是集合类的一个帮助类,包含了各种有关集合操作的静态多态方法,用于实现各种对集合的搜索、排序、线程安全化等操作。此类不能被实例,是一个工具类,服务于Collection框架。
14.Java的四种引用**强引用:**强引用在程序内存不足时(OOM)时也不会被回收。
String str = new String("Str");
**软引用:**程序内存不足时,会被回收。使用场景:创建缓存
SoftReferencewrf = new SoftReference<>(new String("str"));
//这里软引用指的是指向new String(“str”)的引用
**弱引用:**只要JVM垃圾回收器发现,就会回收。使用场景:java.util.WeakHashMap中的key就是弱引用,一旦不需要某个引用,JVM自动帮我们处理。
WeakReferencewrf = new WeakReference<>(str);
**虚引用:**虚引用回收机制和弱引用差不多,但是在被回收之前,会被放入ReferenceQueue中。(其他引用是被回收后才被传入ReferenceQueue)。使用场景:用于销毁前的工作。(虚引用创建时,必须带有ReferenceQueue)
PhantomReferenceprf = new PhantomReference<>(new String("str"),new ReferenceQueue<>());
这几类引用,都是指向对象本身的引用,而不是指向Reference的四个子类的引用。
15.泛型泛型是Java SE1.5之后的特性。《Java核心技术》中对泛型的定义:
“泛型”意味着编写的代码可以被不同的类型的对象所重用
实现方式:
类型擦除(在生成的Java字节代码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,会被编译器在编译的时候去掉,这个过程称为类型擦除)。
特点:
泛型没有自己独自的class对象。
静态变量是被泛型类的所有实例所共享的。
泛型只有编译阶段有效。
泛型有三种使用方式:泛型类,泛型接口,泛型方法。
优点:
一次性开发,测试和部署。
编译器支持和类型安全。
不会强行对值类型进行装箱和拆箱
封装共性问题,简化代码
比Object类范围小,提高程序运行效率。
- new创建新对象
- 通过反射机制
public class Demo {
public static void main(String[] args) {
String str1 = new String();
try {
Class Str = Class.forName("com.test.Demo");//通过class.froName()
//构造器
Constructor c= Str.getConstructor();
//通过构造器实例化
Demo d = (Demo)c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 采用clone机制
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
try {
Demo demo2 = (Demo)demo.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
- 通过序列化
// 序列化就是将对象变为输出字节流
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("Demo.obj"));
os.writeObject(student);
os.writeInt(10);
os.writeObject(null);
os.close();
// 反序列化
ObjectInputStream is = new ObjectInputStream(new FileInputStream("Demo.obj"));
17.hash碰撞
在产生hash冲突时,两个不相等的对象就会有相同的 hashcode值。
解决方式:
拉链法。每个哈希表节点都有一个next指针,多个哈希表节点可以利用next指针构成一个单链表,被分配到同一个所有上的多个接地那可以用这个单项链表进行存储。
开放定址法。一旦发生冲突,就去寻找下一个空的散列地址,之哟啊散列表足够大,空的散列地址总能找到,并将记录存入
再哈希。又叫双哈希发,有多个不同的hash函数,当发生冲突时,使用第二个,第三个…等哈希杉树计算出地址,直到无冲突。
浅拷贝:
被复制的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。(浅拷贝仅仅复制所考虑的对象,不复制他所引用的对象)
深拷贝:
被复制的对象的所有变量都含有与原来的对象相同的值,而那里引用其他对象的变量将指向被复制过来的新对象,不再指向原来的那么被引用的对象。(深拷贝吧要复制的对象所引用的对象都有复制了一遍)
修饰类,不可以被继承
修饰方法,不能被重写
修饰变量,不可以被改变,修饰引用,表示引用不可变,引用指向的内容可变
修饰常量,在编译阶段会存入常量池
编译器对final域要遵守两个重排序的规则。
静态方法,静态变量。属于类的静态资源,类实例共享
静态块,多用于初始化操作,优化性能
静态导包:import static java.lang.Math.*; import static是jdk1.5之后引入的新特性。用于指定导入静态资源.
false,因为浮点数不能完全精确的表示出来。
22.a=a+b与a+=b有什么区别+=操作符会隐式自动类型转换,此处a+=b隐式的将加操作的结果类型强制转换为持有结果的类型。
byte a = 127; byte b = 127; b = a+b;//编译报错 b+=a; //ok,b自动升为int类型23.try catch finally中,try里有return,finally会执行吗
执行,并且finally的执行遭遇try中的return。
不管有没有异常,try和catch有没有return,finally都会被执行
finally中有return会提前结束程序
24.Exception和Error Exception:1.运行时异常(RuntimeException),编译器不会检查。
常见的五种运行时异常:
ClassCastException:类转换异常
IndexOutOfBoundException:数组越界
NullPointerException:空指针
ArrayStoreException:数据存储异常,操作数组的类型不一致
BufferOverflowException:缓存异常
2.被检查异常:Java编译器会检查它。
常见的异常:
IOException,FileNotFoundException,SQLException。
Error:和运行时异常一样,编译器不会检查。当资源不足,约束失败,或是其它程序无法继续运行的条件发生时,就会产生错误。程序本身无法修复。
25.OOM和SOFOOM:
OutOfMemoryError
1.Java Heap溢出。
2.虚拟机栈和本地方法栈的溢出
3.运行时常量池溢出
4.方法区溢出
SOF:
StackOverflow,堆栈溢出
当程序递归太深而发生堆栈溢出,抛出该错误。
1.递归调用2.大量的循环或死循环3.全局变量是否过多4.数组、List、Map数据过大
26.线程、程序和进程的基本概念,它们之间有什么关系线程:
与进程相似,但线程是比进程更小的执行单位。与进程不同的是,同类的线程共享同一块内存和一组系统资源。被称为轻量级进程。
进程:
是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。
线程的上下文切换比进程的上下文借还要快很多。
程序:
是含有指令和数据的文件,被存储在磁盘或其他数据存储设备中,也就是说程序是静态的代码。
新建状态(NEW):
此时仅由JVM为其分配 内存,并初始化其成员变量的值。
就绪状态(RUNNABLE):
当线程对象调用了 start()方法之后,该线程处于就绪状态。Java虚拟机会为其创建方法调用栈和 程序计数器,等待调度运行。
运行状态(RUNNING):
如果处于就绪状态的线程获得了 CPU,开始执行 run()方法的线程执行体,则该线程处于运行状 态。
阻塞状态(BLOCKED):
阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice,暂时停止运行。 直到线程进入可运行(runnable)状态,才有机会再次获得 cpu timeslice 转到运行(running)状 态。阻塞的情况分三种:
等待阻塞(o.wait->等待对列):运行(running)的线程执行 o.wait()方法,JVM 会把该线程放入等待队列(waitting queue) 中。
同步阻塞(lock->锁池):运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线 程放入锁池(lock pool)中。
其他阻塞(sleep/join):运行(running)的线程执行 Thread.sleep(long ms)或 t.join()方法,或者发出了 I/O 请求时, JVM 会把该线程置为阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O 处理完毕时,线程重新转入可运行(runnable)状态。
线程死亡(DEAD):
线程会 以下面三种方式结束,结束后就是死亡状态。
run()或call()方法执行完成,线程正常结束。
线程抛出一个未捕获的Exception或Error
直接调用该线程的stop方法结束该线程—该方法容易导致死锁,通常不推荐使用。
对于不想序列化的变量,使用transient关键字修饰。
transient:阻止实例中那些用此关键字修饰的变量序列化;当被反序列化时,被transient修饰的变量值不会被持久化和恢复。transient只能修饰变量
29.Java中IO流按流的流向分,输入流和输出流
按操作单元分,字节流和字符流
按流的角色分,节点流和处理流
InputStream/Reader:所有的输入流的基类,前者是字节输入流,后者是字符输入流。
public static void main(String[] args) {
File file = new File("文件路径");
try {
FileInputStream in = new FileInputStream(file);
int n = -1;
byte[] a = new byte[100];
//返回读取的字节数
while ((n = in.read(a, 0, 100)) != -1){
String str = new String(a, 0, n);
System.out.println(in);
}
//返回读取的字节数
while ((n = in.read(a)) != -1) {
System.out.println("字节数:" + n);
String str = new String(a, 0, n);
System.out.println(str);
}
//返回字节对应的数值0-255
while ((n = in.read()) != -1) {
System.out.println("n:" + n);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流。
public static void main(String[] args) {
try {
InputStream in = new FileInputStream("创建新文件的路径");
byte[] bytes = new byte[2]; //这里我写2是为了演示,一般写1024吧
int n;
while ((n = in.read(bytes)) != -1) {
String s = new String(bytes,0,n);//这个不能直接写bytes,不然可能会读错
System.out.println(s);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
30.java反射的作用原理
反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意的一个方法。在java中,只要给定类的名字,就可以通过反射机制来获取类的所有信息。
这样动态的获取信息以及动态的调用对象的方法的功能称为java语言的反射机制
使用场景:
jdbc就是典型的反射。
Class.forName(‘com.mysql.jdbc.Driver.class’);
反射实现的方式:
获取Class对象:
1.Class.forName(“类路径”);
2.类名.class
3.对象名.getClass();
4.基本数据类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象
实现反射的类:
1.Class:表示正在运行的Java应用程序中的类和接口
2.Field:提供有关类和接口的属性信息,以及对它的动态访问权限
3.Constructor:提供有关类的单个构造方法的信息以及它的访问权限
4.Method:提供类或接口中某个方法的信息
反射的优缺点:
优点:
能够运行时动态的获取类的实例,提高灵活性;
与动态编译的结合
缺点:
使用反射性能较低,需要解析字节码,将内存中的对象进行解析
相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)
解决方案:
1.通过setAccessible(true)关闭JDK的安全检查来提升反射速度
2.多次创建一个类的实例时,有缓存会快很多
3.ReflectASM工具类,通过字节码生成的方式加快反射速度
31.说说List、Map、Set三者的区别元素的重复性:List中的元素,有序,可重复性,可为空
元素的有序性:Set中的元素,无序,不重复,只有一个空元素
元素是否为空:Map中的元素,无序,键不能重复,可有一个空键,多个空值



