1.初识JVM**
(JAVA Virtual Machine)
JVM是一种规范,可以使用软件来实现,也可以使用硬件来实现,就是一个虚拟的用于执行bytecodes
字节码的计算机。他也定义了指令集、寄存器集、结构栈、垃圾收集堆、内存区域。
JVM负责将java字节码解释运行,边解释边运行,这样,速度就会受到一定的影响。JAVA提供了另一种
解释运行的方法JIT(just in time),可以一【次解释完,再运行特定平台上的机器码【,高级的JIT可以只能
分析热点代码,并将这些代码转成本地机器码,并将结果缓存起来,下次直接从内存中调用,这样就大
大提高了执行JAVA代码的效率。这样就实现了跨平台、可移植的功能。
\1. JVM是指在一台计算机上由软件或硬件模拟的计算机;它类似一个小巧而高效的CPU。
\2. byte-code代码是与平台无关的是虚拟机的机器指令。
\3. java字节代码运行的两种方式:
1)方式interpreter(解释)
2)Just-in-time(即时编译):由代码生成器将字节代码转换成本机的机器代码,然后可以以较高速度执行。
JAVA的跨平台实现的核心是不同平台使用不同的虚拟机
不同的操作系统有不同的虚拟机。Java 虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,随处
运行
2.编译型与解释型
两者各有利弊。前者由于程序执行速度快,同等条件下对系统要求较低,因此像开
发操作系统、大型应用程序、数据库系统等时都采用它,像C/C++、Pascal/Object
Pascal(Delphi)、VB等基本都可视为编译语言,而一些网页脚本、服务器脚本及辅助开发接口这样
的对速度要求不高、对不同系统平台间的兼容性有一定要求的程序则通常使用解释性语言,如Java、
JavaScript、VBScript、Perl、Python等等。
【Java语言虽然比较接近解释型语言】的特征,但在执行之前已经预先进行一次预编译,生成的代码是介
于机器码和Java源代码之间的中介代码,运行的时候则由JVM(Java的虚拟机平台,可视为【解释器】)解
释执行。它既保留了源代码的高抽象、可移植的特点,又已经完成了对源代码的大部分预编译工作,所以
执行起来比“纯解释型”程序要快许多。
3.重写的注意事项
- static修饰的方法是静态方法,静态方法类一加载方法就执行,静态方法不能够被重写【静态和非静态方法之间也不能进行重写,编译报错】,同名同参不同方法体的静态方法,编译通过,但都是父类指向子类引用对象,无法构成重写;重写针对的是非静态方法;
例如:
public class Person {
public static void test() {
System.out.println(“Person”);
}
}
//编译通过,但不是重写
public class Student extends Person {
public static void test(){
System.out.println(“Student”);
}
}
main:
Perosn p = new Student();
p.test();//输出Person
p = new Person();
p.test();//输出Perosn
4.【匿名代码块和静态代码块的作用】
匿名代码块的作用是给对象的成员变量初始化赋值,但是因为构造器也能完成这项工作,所以匿名代码块使用的并不多。静态代码块只在第一次加载时执行,匿名代码块每次实例化对象时都会执行(相当于在构造方法中赋值) 因此匿名代码块经常被称为构造代码块;
静态代码块的作用是给类中的静态成员变量初始化赋值。
执行顺序:
静态代码块【仅一次】》匿名代码块》构造器【构造方法父类先执行,然后子类】》普通方法
public class Person {
{
System.out.println(“匿名代码块”);
}
static{
System.out.println(“静态代码块”);
}
public Person(){
System.out.println(“构造器”);
}
}
5、方法绑定(method binding)
执行调用方法时,系统根据相关信息,能够执行内存地址中代表该方法的代码。分为静态绑定和动态绑
定。
静态绑定:
在【编译期】完成,可以提高代码执行速度。
动态绑定:
【通过对象调用的方法】,采用动态绑定机制。这虽然让我们【编程灵活】,但是降低了代码的执行速度。这也
是JAVA比C/C++速度慢的主要因素之一。JAVA中除了final类、final方、static方法,所有方法都是JVM在
运行期才进行动态绑定的。
6.抽象类和抽象方法的实际存在意义
打个比方,要做一个游戏。如果要创建多个角色,如果反复创建类和方法会很繁琐和麻烦。建一个抽象类
后。若要创建角色可直接继承抽象类中的字段和方法,而抽象类中又有抽象方法。如果一个角色有很多种
职业,每个职业又有很多技能,要是依次实例这些技能方法会显得想当笨拙。定义抽象方法,在需要时继
承后重写调用,可以省去很多代码。 【建立类似的类,减少代码冗余】
总之抽象类和抽象方法起到一个【框架作用。很方便后期的调用和重写 】
抽象方法是为了【增加程序的可扩展性】。重写抽象方法时即可实现同名方法但又非同目的的要求。
7.接口
1)、Java接口中的成员变量默认都是public,static,final类型的(****都可省略****),必须被【显示初始化】,即接口中的成员变量为常量【(大写,单词之间用"_"分隔) 】
2)、Java接口中的方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化
3)、Java接口中只能包含public,static,final类型的成员变量和public,abstract类型的成员方法
4)、接口中没有构造方法,不能被实例化
5)、一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口
6)、Java接口必须通过类来实现它的抽象方法
7)、【当类实现了某个Java接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象类】
8)、不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例
9)、 一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承.
8.内部类分为四种:
1). 成员内部类(实例内部类、非静态内部类)
成员内部类中不能写静态属性和方法 【因为静态的类加载就执行,比外部类普通方法执行还要快,】
【实例化内部类】
实例化内部类,首先需要实例化外部类,通过外部类去调用内部类
//在A类中申明了一个B类,此B类就在A的内部,并且在成员变量的位置上,所以就称为成员内部类
package cn.kgc.tyl.test1011;
/**
*
* 定义成员内部类
*/
public class Outer {
private int id;
public void out() {
System.out.println("这是外部类方法");
}
class Inner {
public void in() {
System.out.println("这是内部类方法");
}
}
}
*************************************1-1
package cn.kgc.tyl.test1011;
import cn.kgc.tyl.test1011.Outer.Inner;
/**
*
* 实例化内部类
*/
public class TestOuter {
public static void main(String[] args) {
// 实例化成员内部类分两步
// 1、实例化外部类
Outer outObject = new Outer();
// 2、通过外部类调用内部类
Outer.Inner inObject = outObject.new Inner();
// 12合并 Outer.Inner inObject = new Outer().new Inner();
inObject.in();// 打印:这是内部类方法
}
}
/**
*
* 这是内部类方法
*/
**************************************1-2
//测试,调用内部类中的方法
分析:想想如果你要使用一个类中方法或者属性,你就必须要先有该类的一个对象,同理,一个类在另一个类的内部,那么想要使用这个内部类,就必须先要有外部类的一个实例对象,然后在通过该对象去使用内部类
2). 静态内部类
3). 局部内部类
4). 匿名内部类
9. 序列化和反序列化transient【临时的】
1、transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。
2、被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
3、一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。也可以认为在将持久化的对象反序列化后,被transient修饰的变量将按照普通类成员变量一样被初始化
对象的序列化可以通过实现两种接口来实现,若操作的是一个Serializable对象,则所有的序列化将会自动进行,若操作的是 一个Externalizable对象,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关 | |
---|---|
transient临时数据,中途允许改变,用来屏蔽不想序列化的属性 |
一 什么叫序列化
通俗点讲:它是【处理对象流】的一种机制,即可以很方便的保存内存中java对象的状态,同时也为了方便传输。
二 序列化有什么作用【数据的持久化】
1.方便传输,速度快,还很安全,被调用方序列化,调用方反序列化即可拿到传输前【最原始的java对象】,常用于不同进程之间的对象传输
2.方便存储,不管是存储成文件还是数据库,都行,存储为文件,下回要用可以直接反序列拿到对象
三 怎么序列化和反序列化
实现序列化接口就行(里面什么方法都没有,不用管的,只是一个标记接口而已)Serializable;
四 序列化时需要注意事项
为了不必要的报错麻烦: 序列化时最好是定义序列化版本id 即 public static final Long seriaVersionUID = 1L (默认) 或者 xxxxx L(自定义64位都行)
因为反序列化会判断序列化中的id和类中的id是否一样,如果不定义虽然会自动生成,但如果后面改了东西列,所以还是自觉点定义一个id,省去好多麻烦
同时记住【静态变量不会被序列化的】,它可不在堆内存中,序列化只会序列化堆内存
在Java中,下列选项中,与序列化和反序列化有关的是( )。
多选题
FileReader
ObjectOutputStream
transient
DataOutputStream
BC
序列化和反序列【此题双选,未认真读题】
本题考察对序列化和反序列化的理解。ObjectOutputStream是用于序列化输出的类,transient临时数据,中途允许改变,用来屏蔽不想序列化的属性。所以本题选bc
10.Collections工具类
Java中,java.util.Collections类属于()。
单选题
无实例类;
单实例类
有固定个数的实例类
枚举类
A
集合框架包含的内容
本题考查对Collections类的理解。Java中Collections类完全由在 collection 上进行操作或返回 collection 的【静态方法】组成。它包含在 collection 上操作的【多态算法】,即“包装器”,包装器返回由指定 collection 支持的新 collection,以及少数其他内容。因为Collections类提供的方法都是static的,所以可以直接调用执行,不需实例化对象。常见方法实现选择器接口如sort(),shuffle(),reverse。
11.IO输入流输出流【writeUTF()和writeChars()】
package cn.kgc.tyl.test1016;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestIo {
public static void main(String[] args) {
try {
FileOutputStream fos=new FileOutputStream("D:/demotext.txt");
try {
fos.write('a');
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
//题型 1.单选题此程序运行结果是()。
//A 编译错误,write方法参数应该是int类型
//B 用记事本打开demotext.txt文件,发现写入33
//C 用记事本打开demotext.txt文件,发现写入字符a
//D 用记事本打开demotext.txt文件,发现写入为不可识别的编码
//
/**
*
*选C,write(char):两个字节自然输出a,ASCII的小a是65,大A是97,排除法也不会选B
* */
/**
*2.在Java中,DataOutputStream进行二进制文件操作时,写入字符串“abc”使用( )方法。
单选题
print("abc")
writeString("abc")
writeChar("abc")
writeUTF("abc")
D:写入字符串时,ow向文件中保存文件,【chars】:需要细心些;
使用DataInputStream和DataOutputStream读写二进制文件
DataOutputStream类的写入数据的方法基本以write开头,针对字符串写入,有三个方法 字符数组writeBytes(String arg),多字符 writeChars(String arg),以及unicode字符 writeUTF(String arg)。本题答案中只出现了writeUTF方法,答案为D
* */
12.多线程买票问题【while(true)与for循环】
1.while(true)本身就是循环,有自增,自减,就不要调用for.
2.为了共享数据,实现的是同一个实现的runnable接口
package cn.kgc.tyl.test1016;
public class TestBuyTicket {
public static void main(String[] args) {
BuyTicket b=new BuyTicket();
Thread p1=new Thread(b,"张三");
Thread p2= new Thread(b,"李四");
p1.start();
p2.start();
}
}
13.复合主键
【两个主键必须在一起定义,不能分开定义】
错误写法:
CREATE TABLE flight_details4(
flight_prefix VARCHAR(20) NOT NULL primary key ,
flight_id VARCHAR(10) NOT NULL PRIMARY KEY ,
………………其他字符段………………
);
正确写法:
CREATE TABLE flight_details4(
flight_prefix VARCHAR(20) NOT NULL ,
flight_id VARCHAR(10) NOT NULL ,
………………其他字符段………………,
PRIMARY KEY(flight_prefix,flight_id)
);
– 主键约束:学号、课程编号和日期构成组合主键**【复合主键】**
ALTER TABLE result PRIMARY key (stuNo,subject_num,subject_date);
14.【日期函数】获得先前或者现在一个日期的时分秒,年月日
当前日期 current_date() 或者curdate()
当前时间 now() [输出年月日时分秒]
当前时间vs一个给定的时间具体的时间年/月/小时 year(now()) vs hour(arrivaltime);
当地时间 localtime()
系统时间 sysdate()
DATEDIFF() 函数返回两个日期之间的时间。默认是天数【可以有一个形参,指定类型,比如月,年】
adddate() 返回增加天数的日期,默认是天数。只有两个形参,
DATEDIFF(date1,date2) | 返回日期参数date1和date2之间相隔的天数 | SELECT DATEDIFF(NOW**(),** **‘2008-8-8’);返回:**2881 |
---|---|---|
ADDDATE(date,n) | 计算日期参数date加上n天后的日期 | SELECT ADDDATE(NOW(),5**);返回:**2016-09-02 09:37:07 |
---|---|---|
DATEDIFF(datepart,startdate,enddate)
datepart 参数可以是下列的值:
datepart | 缩写 |
---|---|
年 | yy, yyyy |
季度 | qq, q |
月 | mm, m |
年中的日 | dy, y |
日 | dd, d |
周 | wk, ww |
星期 | dw, w |
小时 | hh |
分钟 | mi, n |
秒 | ss, s |
毫秒 | ms |
微妙 | mcs |
纳秒 | ns |