Java基础:
Java数据类型:
基本数据类型:
数值型:
整数型:
Int,byte,short,long
小数型:
float,double
非数值型:
char boolean
引用数据类型:
数组 array
接口 interface
类 class(String字符串)
注:byte1个字节,short2个字节,long8个字节,int4个字节(一个字节八位)
Float单精度,32位 double双精度64位 char单一的 16 位 Unicode 字符
数据的类型转换
Char
Short --> int -->long--> float--> double
Byte
byte/char/short计算的时候自动转换成int类型
自动类型升级:小转大 强制类型转换:大转小 boolean不参与类型转换
short i=3;
i=i+3; ①
i+=3; ②
①是错误的,②是正确的。①中因为i是short,参与运算时自动转成了int,int>short,会出现强制类型转换。②中因为+=是java的复合赋值运算符,它的底层代码实现了强制类型转换。
i++与++i
i++先赋值后加 ++i先加后赋值
Switch语句的注意事项
Switch后面只能是byte,short,int,char jdk1.7后可以有string
break和continue的区别
break是跳出循环、结束循环(结束的是break所在那一层的循环)
continue没有结束循环,进入下一次循环。后续代码不执行。
数组的特点
数组中可以存放进本数据类型,也可以存放引用数据类型
数组的长度不能改变,数组的插入删除比较麻烦,但是查询比较快
数组的赋值
动态赋值
int[] arr=new int[6];
arr[0]=12;
arr[1]=57;
arr[2]=34;
arr[3]=23;
arr[4]=15;
arr[5]=49;
静态赋值
int[] arr=new int[]{12,57,34,23,15,49};
简写方式:int[] arr={12,57,34,23,15,49}; 推荐使用
二维数组
动态赋值:
int [][] arr=new int[3][5];
arr[0][0]=30;
arr[0][1]=50;
arr[0][2]= 0;
arr[0][3]=15;
arr[0][4]=8;
arr[1][0]=30;
arr[1][1]=50;
arr[1][2]= 0;
arr[1][3]=15;
arr[1][4]=8;
静态赋值:
int[][] arr=new int[3][];
arr[0]={1,2,3,4};
arr[1]={2,3};
arr[2]={0}
int[][] arr=new int[][]{{1,2,3,4},{2,3},{0}}; 标准写法
简写形式:int[][] arr={{1,2,3,4},{2,3},{0}};
方法重载 overload:在同一个类中,允许出现一个以上同名方法
//方法名称 参数列表不同(参数的个数,参数的数据类型的顺序不同) 方法重载 和返回值没有关系
//同名不同参 面向对象多态的一种体现
//编译时多态 运行时多态
同名不同参(方法的名字一样,参数列表不一样:参数的个数不同,数据类型的顺序不同)
和返回值没有关系。
方法重载是面向对象多态性 静态多态的一种体现
好处:方便用户更灵活选择
重写:子类对父类方法的改造 :override 重载:overload
a. 发生在继承关系中(子父类的关系中)
b. 方法名、参数列、返回值一样
c. 子类重写方法的访问权限修饰符>=父类被重写方法的修饰符
d. private修饰的方法不能被重写
class A{
private void show(){}
}
class B extends A{
public void show(){}
}
e. 父类被重写方法抛出了异常,如果子类重写方法也选择抛出异常,子类重写方法异常的异常一定要小于等于(<=)父类被重写方法抛出的异常。
成员变量和局部变量的区别
1) 在类中的位置
局部变量:方法中或者方法的参数列表
成员变量:类的里面,方法的外面
2) 在内存中的位置
局部变量:栈
成员变量:堆内存 new
3) 初始值不同
局部变量:必须赋初始值
成员变量:有默认的初始值 int 0 double 0.0 Stirng null
4) 生命周期不同
局部变量:随着方法的调用而存在,随着方法的结束而消失
成员变量:随着对象的创建而存在,随着对象的消失而消失
this的使用
1) 可以调用本类的成员变量和成员方法
示例:
写法:this.变量名 this.方法名()
2) 可以在调造方法中调用构造方法(也可以调用成员)
只能在构造方法中调用构造方法,普通方法不可以
而且只能写在构造方法的第一行。
语法:this()调用无参构造 this(参数):调用带参数的构造方法
3) this表示本类对象的引用
匿名对象
没有名字的对象
1)如果对象的方法只想调用一次,可以使用匿名对象
使用语法方便,而且便于垃圾回收。
如果对象的方法想多次调用,不建议使用匿名对象。因为会浪费内存空间。
2)可以当作参数
垃圾回收机制
java的线程
前台线程:用户线程
后台线程:(守护线程、精灵线程) 垃圾回收机制属于后台线程
java垃圾回收机制是java jvm(虚拟机)内部 优先级别比较低的后台线程
垃圾回收机制是和堆内存有关,和栈内存无关
垃圾回收机会 在不确定的时间 来回收垃圾。
对象变成垃圾有三种情况:
1) Student s=new Student();
s=null;
2) 调用一次方法的匿名对象
new Student().show();
3) 循环中定义的对象
for(int i=1;i<=3;i++){
Student s=new Student();
}
访问权限修饰符
public:一个项目中所有类 公开的、公共的
protected:受保护的: 同一个包中的类、本类、其他包的子类
default:默认的、友好的friendly String name;
同一个包中的类、本类
private:私有的 本类
类的成员(成员变量和成员方法):4个
类的修饰符:public default
|
public |
protected |
default |
private |
本类 |
√ |
√ |
√ |
√ |
同一个包中的类 |
√ |
√ |
√ |
|
不同包中的子类 |
√ |
√ |
|
|
其他包中的类 |
√ |
|
|
|
super和this的区别
this:本类
可以调用本类的成员变量和成员方法(在普通方法、构造方法)
this.变量名 this.方法名
在构造方法调用本类的其他重载构造方法
this()第一行
this(参数) 只能在构造方法中使用,不能在普通方法中使用
super:父类 继承关系中
可以调用父类的成员变量和成员方法(在普通方法、构造方法)
super.变量名 super.方法名
任何一个类(除了object)的构造方法的第一行都有一个系统默认的super()
super()调用父类的无参构造
super(参数)调用父类的有参数的构造方法
一个构造方法中,super()和this()不能同时使用
多态:
不同的对象针对同一个行为 作出不同的反应 多态:多种形态
1、要有继承、实现
2、重写
3、父类的引用指向了子类的对象 Aniaml a=new Dog();
static:静态的
a) 特点:
1) 随着类的加载而加载
2) 优先于对象存在
3) 被类的所有对象共有 比如:饮水机static 水杯private 国籍static
4) 可以通过类名.变量名(类名.方法名)来调用
b) static可以修饰成员变量
c)
静态变量、类变量
调用方式:
1) 对象名.变量名
2) 类名.变量名 è推荐使用
d) static可以修饰成员方法,不能修饰局部变量。
1) static修饰的方法(前提:不使用new对象)只能调用static修饰的成员
2) 在static修饰的方法中不能使用this.变量(this.方法)
3) 在普通方法中可以使用static修饰的成员
4) static不能修饰构造方法
原因:构造方法是用来创建对象的,而static是跟着类走的。
5) 静态方法只能重写静态方法,不能重写非静态的方法。
e) static可以修饰代码块 static{代码块;} :静态代码块
特点:随着类的加载而加载,只执行一次。
不管new多少个对象,只执行一次
f) {}:构造代码块,跟着对象 优先于构造方法执行,给对象成员初始化
静态代码块>构造代码块>构造方法
构造代码块:new多少个对象就执行多个构造代码块,只不过,它优先于构造方法执行。
g) static类变量和成员变量的区别
1) 所属不同
类变量:所属于类 类变量、静态变量
成员变量:所属于对象 实例变量、全局变量、属性、字段
2) 内存的位置不同
类变量:方法区中的静态区
成员变量:堆内存
3) 生命周期不同
类变量:随着类的加载而加载,随着类的消失而消失。生命周期最长。
成员变量:随着对象的存在而存在。
4) 调用方式不同
类变量:两种调用方式
对象名.变量名
类名.变量名(推荐使用)
成员变量:对象名.变量名
5)
h) 不可以把项目中所有的成员变量全部设成static的。
因为static变量是随着类的存在而存在,生命周期很长。如果项目中所有的成员变量全部是static的,会消耗内存。一般情况下,把共享的数据定义成static的,比如:饮水机、国籍。
i)
final:最终的,终态的,不能被改变的
1) 可以修饰成员变量
常量(大写),值不能被改变 public staitc final double PI=3.14159;
2) 可以修饰方法
不能被重写
3) 修饰类 final class Demo{}
类不能被继承
4) 小例题
final int arr[]={3,2,4};
arr[1]=5; 正确的 ,数组中的值是可以被改变的
int brr[]=new int[3];
arr=brr; 错误的,因为数组是final,地址不能被改变
5) 如果局部内部类中调用它所在方法中的变量,此变量必须是final的。
抽象类和接口的区别?
a. 相同点:都不能new对象
b. 不同点:
1) 构造方法
抽象类:可以有。是为子类准备的。
接口:没有,因为它是一个interface,不是一个类。
2) 变量
抽象类:变量的访问修饰符可以任意:public /private/ default/ protected..
接口:只能是public static final
3) 方法
抽象类:可以有普通方法,也可以有抽象方法
接口:只能是抽象方法public abstract
4) 继承关系:
抽象类:有关系(is a)的类才能继承抽象类(类)
接口:无关的类可以实现同一个接口
Student学生 Feiji飞机 Dog狗
public interface Run{}
类和类:单继承
类和接口:多实现
接口和接口:多继承
异常
Throwable(类):java.lang包
|--Error:严重的错误(JVM内存耗尽、堆栈溢出,不需要异常处理机制来处理)
|--Exception:异常
|--检查性异常:(异常处理机制针对的):必须处理
IOException为代表
|--非检查性异常(运行时异常):编译时不报错,运行后才会出现异常
RuntimeException
以下是常见的几种运行时异常:
ArrayIndexOutOfBoundsException 数组下标越界
NullPointerException:空指针异常
ClassCastException:类型转换异常
ArithmeticException:除数不能为0
可处理,可不处理
Java高级
1、java的集合体系来说Collection是一个顶级接口,JDK并没有直接提供实现类来实现接口,而是间接的提供了Set和List接口进行实现
2、List接口:ArrayList LinkedList
1) ArrayList: 有序的,重复的集合可以通过索引进行数据的访问,常用的API get add remove clear contains ... 如果遍历集合的长度使用size()方法,数组中的Length属性区分。arraylist中有toArray方法,他的作用是将集合转换为数组的,(版本的不同7以下 classCastException,7以上的版本进行自动的拆箱装箱)。
2) ArrayList:源码,ArrayList底层的实现是有数组实现的,当我们使用ArrayList默认的构造方法的时候,底层会生出一个长度为10的Object类型的数组,如果说长度超过10个,底层会生成新的数组,数组的长度(扩容)数组*1.5+1(针对JDK6 JDK7是使用的自动扩容机制)。
3) 当我们直接打印List变量的时候,List中每个元素的toString()方法,在我们的实际开发中,我们通常都会重写toString方法,方便我们后续的调试
4) ArrayList:进行固定位置的添加和删除的时候,尽量不要用remove和add(@,@)方法,如果进行添加和删除,必须整体移动集合,代价是比较高的
5) LinkedList:对于LinkedList来说,也是List的实现类,我们建议使用add第二个方法重载进行数据的添加
6) LinkedList:源码:LinkedList底层是由链表实现的(双向链表),源码中的Node元素就是我们演示中的Element元素,
7) 集合转换为数组使用集合的toArray方法,数组转换为集合使用Arrays.asList(可变参数),可变参数可以使用数组赋值。
8) ArrayList 适合于读取数据,LinkedList适合于操作数据(添加 删除等)
9) 使用LinkedList实现Stack的数据的存取
10) ArrayList和LinkedList的比较:
3、当使用HashSet时,hashcode()就会调用,hashset判断已经存储在集合中的对象的hashcode值是否与新添加的hashcode值一致,不一致,直接添加。如果一样,再进行equals方法的比较,如果equals方法返回true,说明对象存在了,就不会添加新的元素,否则添加进去。
4 、TreeSet是一个遵循自然排序的集合,我们需要在声明TreeSet的时候必须定义一个规范,而这个规范就是Compator接口的实现类
5、Set的遍历,我们使用Iterator进行遍历 hashNext next
1)第一种使用While去遍历Iterator hashnext判断是否有下一个值,next方法进行值的读取
2)for循环,进行set元素的获取
6、Collections常用的方法max min shuffle sort copy就是一个集合的辅助类
7、Vector同ArrayList使用,Vector是线程同步的,安全,而ArrayList是非线程安全的,但是ArrayList的效率要高
8 、Map(映射):K,V键值对的映射,在Map结构中Key是不允许重复的,Value是可以重复的,每一个键最多只能映射一个值
9、HashMap中的key的集合可以使用Set接口进行表示,Value的集合可以使用CollectionList表示
10、HashMap遍历的方式有两种
1)思路:通过map中keyset()方法获取所有的Set集合,遍历Set集合,通过map.get(key)获取到value
2)、Map中的内部类Entry对象,Entry对象维护了HashMap中的k v键值对,也就是说KV组成了一个Entry对象,所以我在遍历HashMap的时候,我们hashMap中的所有的Entry对象遍历出来,然后利用Entry对象的getKey getValue方法获取到KV值
3)、HashMap和HashTable比较:arraylist vector Map线程不安全 性能高 Table线程安全 效率低,properties KV DB.properties
11 泛型:就是变量类型的参数化,目标:编译时候不报错,运行的时候一定不会报错
泛型是实现通用框架的基础,定义一个类的时候<>定义当前类的变量的类型A T,声明这个类的对象的时候,你传具体的变量的类型。
12 补充:HashSet底层的实现是由HashMap实现的,当我们调用HashSet中的add方法时,本质上是往HashMap中的Key放入了我们添加的值,而HashMap中的Value永远常量值,Object
13 对于Java中常量的命名规范:所有的单词都是大写的,如果有多个单词,那么每个单词之间使用下划线连接
public static final String JAVA_CLASS_TEST=100
Lesson4
14 字符流:如何 将字节流转换为字符流
1)InputstreamReader 将输入字节流转换为输入字符流
2) OutputStreamWriter 将输出的字符流转换为输出的字节流
3)FileReader 以字符的方法进行文件的读取(输入)Fileinputstream
4)FileWriter 将字符写入到目标文件 FileOutputStream
15 ByteArrayInputstream: CharArrayReader
16 源码:当我们使用inputStream方法的read方法读取字节的时候,Java并没有提供read方法的实现,而是交由底层操作系统来实现的。
17 inpustream outputstream reader writer
字节:Fileinputstream bytearrayInpustream
处理流:bufferedinputstrem datainputstream
18 System.in out在流系统中称为标准的输入和输出 键盘就是标准的输入 控制台就是标准的输出
19 序列化:将对象转换为字节保存起来,然后再以后还原这个对象,这种机制就做对象的序列化。
20 一个类的对象要想实现序列化必须实现Serializable接口。
21 流:ObjectInputStream ObjectOutputStream
22 序列化的过程中,static类型的变量是无法序列化的,如果在序列化的过程中,A包含了对B的引用,那么B也会同A一并的序列化,如果B不予许序列化,那么这时当A序列化的时候,就会发生异常,这时候必须将B类型的变量使用transient关键字进行标注
23 当我们进行序列化和反序列化的时候,如果我们实现了
private void writeObject
private void readObject
那么序列化来说可以让我们更加随心所欲的定义那些属性需要序列化和反序列化。
线程与进程
1 、进程:运行中的程序。(程序是静态的概念,进程是动态的概念)。独立性、动态性、并发性
2、进行是由线程来组成的。
3、目的:最大化的使用CUP,提高当前应用的性能。
4、
5、优点:
1)多线程共享内存,节约系统 资源成本
2)充分利用CPU,执行并发任务,效率高
3)Java内置多线程编程
6、Java如何实现多线程?
1)Thread类
2)Runnable
3) Calable接口
4)Futrue接口
7、对于我们的Java系统来说都是针对于多线程运行的,我们的main方法就是一个主线程
8、线程的实现有两种方式:1)继承Thread类2)实现Runnable接口 run方法就是线程执行的 代码 start()才是真正的执行线程的方法
9、Thread类和Runnable接口的区别:
1)Thread类也实现了Runnable接口,因此他实现了Runnable接口中的run方法
2)Thread类中有Runnable接口的引用,这个变量名字 叫做target,
3)当我们使用第一种方式生成线程的时候,我们需要重写run方法,因为Thread类继承了Runnable接口,而且run方法中如果没有传递实现了Runnable接口的实现类的话,run方式就是个空方法,什么都不做。
4)使用第二种方式创建线程的时候,我们需要实现Runnable接口,然后将实现了Runnable接口的实现类以参数的方式传递到Thread类中,那么当调用Thread类中的run方法的时候,我们就是调用的实现了Runnable接口的那个run方法
10、对于线程的执行是不可控的,那么我通常会通过一些手段来控制线程
1)循环
11、多线程对同一资源进行访问的注意点:
1)如果一个类中的变量是一个全局变量,多线程对这个对象的变量进行操作的时候,他们对成员变量的操作会影响到其他的线程(如果说一个线程修改了全局变量,那么其他线程访问该变量的时候,一定会受到影响,比如A a=1 a=1,对于成员变量来说,线程是共享成员变量的
2)如果一个类的变量是局部变量,多线程对这个对象的局部变量进行访问的时候,每一个线程都会对局部变量进行一次赋值(copy),换句话说,每一个线程都有自己的一份局部变量,对于局部变量的改变不会影响到其他线程。
12、线程的同步:
我们使用Synchronized关键字进行线程的同步,Synchronized就是一个锁。
13、synchronized:当使用多线程访问同一个资源的时候,有可能会发生线程的同步问题,那么我使用Synchronized关键字进行同步的解决
14、Java中每一个对象都有一个默认的锁或者是监视器(monitor),当访问某个对象的Synchronized方法的时候,表示将该对象上锁,这时候任何的线程都无法方法这个Synchronized方法方法了,直到该线程运行完毕或者发生异常的时候,该线程会释放锁。
15、任何一个类不管生成多少个对象,JVM他们永远只对于一个Class对象
16、使用Static 和Synchronized关键字修饰方法的时候,他上锁的对象是当前对象的Class对象。因此当线程分别访问同一个类的两个对象的Static \synch方法时,他们执行的是顺序。
用synchronized关键字声明的静态方法,同时只能被一个执行线程访问,但是其他线程可以访问这个对象的非静态方法。即:两个线程可以同时访问一个对象的两个不同的synchronized方法,其中一个是静态方法,一个是非静态方法。
在一个对象被某个线程锁定之后,其他线程是可以访问这个对象的所有非同步方法的
17、当使用Sleep方法进行线程休眠的时候,线程不会让出资源的。
18、wait()、notify()通常情况是结合在一起的,他们必须定义在synchronized块或者synchronized修饰的方法中的。
数据库连接JDBC
1 、JDBC(Java database connection),JDBC就是使用Java操作数据库的简称。
2、1)DriverManager:管理数据驱动的
2)Connection:建立应用和数据库的连接的
3)Statement(prepredStatment):发送各种SQL语句和返回结果集的
4)ResultSet:丛Statement中执行的各种结果
3、进行数据库的连接
1)加载驱动类Mysql:com.mysql.jdbc.Driver
Oracle:oracle.jdbc.driver.OracleDriver
2) 使用DriverManager进行连接 Mysql:
jdbc:mysql://localhost:3306/neusoft
Oracle:jdbc:oracle:thin:@localhost:1521:orcl
4、Driver接口:他出现的目的就是为各个供应商提供一种标准。
5、JDBC中如果执行的增删改 statment.execute(sql) sql executeQuery
6、PreparedStatement的使用
1) 避免SQL语句的拼接,减少出错
2) 有效的避免SQL注入
7、如何获取数据库中查询出来的字段?
1)ResultSetMetaData
部分简答题
请描述ArrayList和LinkedList的区别
Arraylist采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常麻烦
Linkedlist采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个链接的索引 但是缺点就是查找非常麻烦 要从第一个索引开始
请详细描述"=="和equals方法的区别
equals()方法是Object类的方法,在Object类中比较两个对象引用是否指向同一个对象,一般都被子类方法覆盖,不再比较引用的值
"=="是比较运算符:,当比较基本数据类型时,比较两个数据值是否相等;当比较引用数据类型时,比较两个引用是否指向同一个对象。
描述HashMap和HashTable的区别
两者都属于Map接口的实现类,都实现了键值对映射。
区别在于:
HashMap 允许一个 null 键和多个 null 值,HashTable 不允许 null 键和 null 值。
由于HashTable诸多方法是线程同步的,因此性能上要比HashMap差 。
请描述线程都包含哪些状态(包含不同的阻塞状态),并说明状态之间如何转换。
主要状态包括:新建、就绪、运行、阻塞、死亡状态。 --2分
其中阻塞状态又可分为:等待阻塞、同步阻塞、其他阻塞状态。 --1分
各状态之间切换如下:
1.新建状态(New):用new语句创建的线程对象处于新建状态
2.就绪状态(Runnable):当一个线程对象被创建后,其他线程调用它的start()方法后,该线程就进入就绪状态,Java虚拟机会为它创建方法调用栈和程序计数器,处于这个状态的线程位于可运行池中,等待获得CPU 的使用权。
3.运行状态(Running):当处于就绪状态的线程对象获得CPU 的使用权之后,该线程就进入运行状态,处于这个状态的线程对象占用CPU,执行线程体程序代码。在并发运行环境中,如果计算机中有只有一个CPU,那么任何时刻只会有一个线程对象处于这个状态。如果计算机有多个CPU,那么同一时刻可以让几个线程对象占用不同的CPU,使它们处于运行状态。只有处于就绪状态的线程才有机会转到运行状态。
4.阻塞状态(Blocked):阻塞状态是指线程因某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,Java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才有机会转到运行状态。
阻塞状态可分为以下3种,分别是:
等待阻塞状态:也叫位于对象等待池中的阻塞状态(BlockedinObject’swaitpool),当正在运行的线程执行某个对象的wait()方法时,Java虚拟机就会把该线程放到这个对象的等待池中。
同步阻塞状态:也叫位于对象锁池中的等待状态(BlockedinObject’slockpool),当正在运行的线程试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他线程占用,Java虚拟机就会把这个线程放到这个对象的锁池中。
其他阻塞状态:当正在运行的线程执行了sleep()方法,或者调用了其他线程的join()方法,或者发出了I/O 请求时,就会进入这个状态。当sleep()方法超时、join()等待线程终止或者超时、或者I/O 处理完毕时,线程重新转入就绪状态。
5.死亡状态(Dead):当线程结束run()方法的执行时,就进入死亡状态,该线程结束生命周期。线程有可能是正常执行完run()方法退出,也有可能是遇到异常而退出,不管线程正常结束还是异常结束,都不会对其他线程造成影响。
请简述使用JDBC调用数据库的步骤.
1.载入JDBC驱动程序
2.定义连接URL
3.建立连接
4.创建Statement对象
5.执行查询或更新
6.结果处理
7.关闭连接
int和Integer有什么区别
int是Java的原始数据类型,也叫基本数据类型。Integer是Java中为int提供的包装类,它是类而不是基本数据类型,它的内部其实包含一个int型的数据。
描述Set、List、Map三个接口,在保存元素时,各有什么特点
Set、List中只能存储单列元素。
Map存储键值对。
Set保存元素时,不允许重复、无序。
List保存元素时,允许重复、有序。
Map保存元素时,不允许键重复。
Collection 和 Collections的区别
Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。
Collection是个java.util下的接口,它是各种集合结构的父接口
String和StringBuffer的区别
String:是不可改变的字符串类。
StringBuffer:是可变的字符串类。
StringBuffer是线程安全的,在多线程程序中也可以很方便的进行使用,但是程序的执行效率相对来说就要稍微慢一些。
描述如何创建和启动多线程。
创建:
第一种方法:继承Thread类,重写run()方法。
第二种方法:实现Runnable接口,实现run()方法。
启动:
调用start()方法来启动线程