java知识模块:
1.基础知识,数组,字符串,正则表达式;
2.类和对象,接口,继承,多态,抽象类,内部类,泛型,java常用类库。
3.异常处理; 4.IO; 5.事件处理;
6.多线程; 7.集合类 8.网络通信; 9.JDBC操作数据库 10.反射 11.序列化
一、运行机制、内存分配
1.java执行步骤为:使用javac将.java文件编译成.class文件;然后执行一个.class文件
2.java程序在JVM内运行,具有可移植性.
3.java的参数传递是值传递,而不是引用传递。
值可以理解为内存地址,引用即是地址指向的内容。
4.栈内存:在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
堆内存:堆内存用来存放由new创建的对象和数组。
5.java具有自动的垃圾收集机制。
二、类和对象
1.类是描述同一类型的对象的抽象概念,对象是类的一个具体实例。
2.对象可以看成是静态属性(成员变量)和动态属性(方法)的封装体.
命名规范:方法和属性的第一个首单词小写,之后每个单词首字母要大写。比如getInfo();
3.当创建类时,就是在描述那个类的对象的外观与行为。执行new来创建对象时,数据存储空间才被分配,其方法才供外界调用。
4.构造方法的名称必须与类名完全相同 。构造方法没有返回值。
java中执行子类的构造方法时,会先执行父类的构造方法。
5.初始化切记:初始化的顺序是先静态对象,而后是“非静态”对象。
对于静态变量、静态初始化块、变量、初始化块、构造器,
它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器。
6.静态代码块在类加载时调用,并且只调用一次。
静态代码块最常用的作用就是:给一个对象的属性初始化。
7.使用get和set方法,是为了保证程序的封闭性和安全性。。
如果直接把数据设为public ,那么数据很可能会混乱,无法维护。
8.修饰符范围
private:当前类中才可以使用;
public :完全公开;
protected:子类可以访问。
static(静态):可以修改属性、方法,还可以修饰代码块。jvm在加载时会先加载静态代码块,再加载其他代码块。
所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在,gc通常是不会回收这个对象所占有的堆内存的。
static变量和static方法可以通过类名直接调用。
final :final可以修饰类,表明该类不可以被继承。另外,final还可以修饰变量。对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
四、泛型
1.泛型:在定义集合的时候同时定义集合中对象的类型。
2. List <?>
List<?> 这样去定义的话和List<Object>是一个意思,这样就可以避免到时候从list中取值使用的时候出现运行时异常,
加上泛型,定义之后,在往list中添加元素的时候就必须是定义的元素,否则编译会报错,例如定义List<String> a=new ArrayList<String>();
这样的话,a中就只能添加字符串,其它类型添加不了,特别作用就是避免运行时异常
五、抽象类
1.当一个类被声明为abstract时,称为抽象类。
public abstract class leader{ }
2.抽象类不能实例化,而且抽象类中的方法只有方法名,没有方法体.
public abstract void worker();
3.含有抽象方法的类,必须是抽象类.
六、内部类
1.每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个实现,对于内部类都没有影响。
匿名内部类也就是没有名字的内部类,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写.
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
七、继承
1.继承是所有面向对象语言,包括JAVA语言不可缺少的组成部分。
当创建一个类时,除非已明确指出要从其他类中继承,否则就是在隐式地从JAVA的标准要类Object进行继承。
2.为了继承,一般的规则是将所有的数据成员都指定为private,将所有的方法指定为public.
3.this 关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。
super出现在继承了父类的子类中。super必须放在类的首行.
super.xxx();(xxx为方法名) 意义为,直接访问并调用父类中的方法。
4.组合:只需将对象引用置于新中即可。在新类中嵌入的现有类的对象一般为private.
5."is-a"的关系是用继承来表达的。而"has-a"的关系则是用组合来表达的。
如果一个类继承自另一个类,那么它们是“is-a”的关系,如果一个类的成员中引用了另一个类,那么它们是“has-a”的关系。
八、多态
1.多态,顾名思义,就是有多种表现形式。
Dog jack=new Animal();
2.多态有两种表现形式:重载和重写.
a.重载(overload),一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同.
他们之间毫无关系,是不同的函数,只是可能他们的功能类似,所以才命名一样,增加可读性.
b.重写(override),发生在子类中,即有继承的情况下才有重写发生。继承一个类,也就有了父类了全部方法,
如果你感到那个方法功能要变,那就把那个函数在子类中重新实现一遍。这样再调用这个方法的时候,就是执行子类中的过程了。
九、接口
1.Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现.
2.接口中的方法只有定义而没有被实现;
public interface Calculate{
final float PI=3.14159f;
float getArea(float r);
float getCircumference(float r);
}
3.接口和抽象类最大的一个区别,就在于Java抽象类可以提供某些方法的部分实现,而Java接口不可以。
4.接口没有构造方法,只能通过实现类来初始化。
十、数组
1.数组的创建和初始化:
int month[]=new int[12]; //int month[]为声明部分,new int[]为分配内存。
int arr[]=new int[]{1,2,3,12,24};
2.length的用法。
int[] a=new int[10];int len=a.length;
这个是数组的length属性
String str="abc";int len=str.length();
这个是String的length方法
3.二维数组初始化,行数可以不写,但是列数必须写。
4.数组的foreach用法。for(int k:arr)。
int[] arr= {1,2,3,4,5};
for(int k:arr) System.out.println(k); //此处的k就是数组元素a[0],a[1]....
相当于:
int[] arr= {1,2,3,4,5};
for(int i=0; i<arr.length; i++)
{
int k = arr[i];
System.out.println(k);
}
5.对数组进行排序,可以使用sort()方法;
数组的复制,可以用copyOf()方法。
十一、字符串
1.toString()是Object类里的方法。所有类都继承于Object,所以所有类都有toString()方法,该方法可以重写。
toString()方法就是把对象转换成String类型,转换的算法根据类型和实际需要而定。
2.indexOf(char a) //获取指定字符的索引位置
lastIndexOf(char a) //获取指定字符的最后一个索引位置
charAt(int index) //获取索引位置的字符
replace() //用于替换指定字符串
substring(beginIndex,endIndex) //获取范围内的字符串,[beginIndex,endIndex),包括开始的索引,但不包括结束的索引
3.split用于分拆字符,该函数返回一个下标从零开始的字符数组,它包含指定数目的子字符串.
split参数可以是普通字符串,也可以是正则表达式。比如 date.split("\.")[0]
4.trim()方法用于去掉字符串前面和后面的空格。
5.indexOf(int ch)返回指定字符在此字符串中第一次出现处的索引。
6.StringBuffer类的方法setCharAt(int index, char ch):修改对象中索引值为index位置的字符为新的字符ch.
7.toUpperCase();转变成大写字母。toLowerCase();即变成小写。
8.比较运算符“=="比较的是内存位置,不适宜拿来比较字符串;
equals()方法用来比较两个字符串.
9.StringBuffer类型转换为string,可以使用toString方法。
append用于向StringBuffer对象添加字符串。deleteCharAt删除指定位置的字符。
insert用于插入。delete删除。reverse用于反转字符串。
10.StringBuffer和StringBuilder区别:StringBuilder性能好,耗时少,线程不安全;StringBuffer耗时较久,线程安全。
String 和StringBuffer的区别:
String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串可以进行修改。
当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。
11.CharSequence与String都能用于定义字符串,但CharSequence的值是可读可写序列,而String的值是只读序列。
12.int i=Integer.parseInt(str); //将字符串转化为对应的数字
13.重写equals时,必须重写hashCode.
equals和hashCode的关系如下所示:
a、如果两个对象相同,那么它们的hashCode值一定要相同;
b、如果两个对象的hashCode相同,用eqauls方法比较它们并不一定相同.
十二、正则表达式;
1.为了检查输入的数据是否满足某种格式,可以使用正则表达式中的matches方法。
2.正则表达式的限定符,\d{3}表示数字出现3次,\p{Upper}{2}表示大写字母出现两次
String str="QQabc1234";
boolean b1=str.matches("\p{Upper}{2}\p{Lower}{3}\d{4}");
3.Pattern是一个正则表达式经编译后的表现模式。
Pattern compile(String regex) 表示将给定的正则表达式编译并赋予给Pattern类。
Matcher对象依据Pattern对象做为匹配模式对字符串展开匹配检查。
运用示例:
String str="1983-07-27"; //检查日期格式是否正确
String regex="\d{4}-\d{2}-\d{2}";
Pattern p=Pattern.compile(regex); //先声明模式
Matcher m=p.matcher(str); //接着再匹配
if(m.matches()) {
System.out.println("日期格式合法");
}else {
System.out.println("日期格式不合法");
}
十三、异常处理
0.RuntimeException, 运行时异常,特点是Java编译器不会检查它。
非运行时异常 (编译异常): 是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常
Error:用于指示合理的应用程序不应该试图捕获的严重问题。如OutOfMemoryError、StackOverFlowError。
1.try {} catch(exception e){ } ;
如果try里面的代码正确,那么程序不经过catch语句直接向下运行;
如果try中如果发现错误,即跳出try去匹配catch,那么try里面的语句就不会被执行。catch 处理之后程序会继续往下执行。
2.e.printStackTrace()方法:在命令行打印异常信息在程序中出错的位置及原因
3.try {}catch(){}finally{}
finally里面的代码,一定会执行。
4.异常可以在方法内通过throw抛出。
public void withAop(int value) { if (value == null) throw new NullPointerException(); } }
也可以在方法后面通过throws抛出。
public void withAop() throws Exception { // ... }
经典博文: Java 异常处理的误区和经验总结
十四、输入/输出
1.字节输入流:InputStream
字节输出流:OutputStream
文件输入流:FileInputStream(只提供对字节的读取方法)
文件输出流:FileOutputStream(对字节的写入,如果文件不存在,会自动创建文件。但是如果路径中的某个文件夹不存在,就会报错"找不到文件")
创建文件: File file=new File("E:/io操作");
获取文件信息的方法:file.getName(); //获取文件名
file.exists(); //判断文件是否存在
字符流:Write,Read
2.字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,
而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。如果字符流没有close,那么缓冲区中的内容不会加载到文件中。
3.流是什么?流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,
如果数据的流向是程序至设备,我们称为输出流,反之我们称为输入流。
4.read()方法读到末尾时,返回值是-1.
5.将字节数组放进文件输出流,才能写入数据。操作完毕,记得关闭流。
还有,进行IO操作时,要加上异常处理。
6.IO中使用了大量的装饰器模式。
7.IO流关闭顺序,先开后关。
十五、多线程
1.java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。
一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限。
调用Thread类的start()方法,就会执行线程,自动启动run()方法
为什么启动线程不直接使用run()方法?线程的运行需要本机操作系统支持。
2.对象“互斥锁”,保证共享数据操作的完整性,“互斥锁”的标记保证在任一时刻,只能有一个线程访问该对象。
3.关键字synchronized用于对象的互斥锁联系,当某个对象有synchronized修饰时,表明该对象任一时刻只能由一个线程访问。(程序锁)
4.Wait和sleep的区别:wait时别的线程可以访问锁定对象,而sleep时别的线程不可以访问锁定对象。
5.notify用于唤醒wait的进程。thread.yield()暂停当前正在执行的线程对象,并执行其他线程
十六、集合
1.ArrayList和Vector都是使用数组方式存储数据,查找数据快而插入数据慢,LinkedList使用双向链表实现存储,插入速度较快。
2.List指的是集合.<>是泛型,里面指定了这个集合中存放的是什么数据.
List<String> list=new ArrayList<String>(); //List是抽象类,不能实例化。只能通过子类实例化
<?>是通配符,List<?> 相当于List<Object>.
同样是存储数据,数组存放基本的数据类型,集合可以存放多种多样的对象。
3.Collection接口定义了存取一组对象的方法,其子接口分别定义了存储方式。Collection是各种集合结构的父接口。
Set:无序且不重复。List:有序且可以重复。
List的有序性表现在输出集合数据的顺序与输入集合数据时的顺序是一致的。
4.List的常用方法:add(),remove(),iterator().
ArrayList可通过get()方法获取对应索引的字符串
5.Map集合中的元素是通过key,value(键值对)存储的。
向Map中添加元素,必须用put();
十七、网络编程
java网络编程提供了两种通信协议:TCP(Transmission Control Protocol传输控制协议)和UDP(User Datagram Protocol数据报协议)
InetAddress类主要表示 IP地址。
getLocalHost()方法获取本机的IP地址,getHostAdress()获取IP地址
URL(Uniform Resource Locator)统一资源定位符.可以直接使用此类找到互联网上的资源。
可以根据指定的URL对资源使用InputStream进行读取.
URLConection是封装在访问远程网络资源一般方法的类,可以建立与远程服务器的连接。
服务器使用ServerSocket等待客户端的连接,每一个客户端使用Socket对象表示.
服务器运行时使用accept()方法等待客户端连接,执行之后服务器进入阻塞状态,直接客户端连接程序才可以继续执行。
为了保证服务器可以同时连接多个客户端,可以加入多线程机制,即每一个客户端连接之后都启动一个线程,这样的话,
服务器就可以同时连接多个客户端了。
十八、反射
1.JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2.反射的核心类:Class类.
Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。
虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。
3.Class类的实例化: Class<?> class=Class.forName("com.example.reflect.ReflectDemo");
forName方法的参数为完整的"包.类"组成的字符串
通过Class完成其他类的实例化:Person person=(Person)Class.forName("com.example.reflect.Person");
4.通过new关键字可以实例化对象,通过Class也能实例化对象,区别在于:
new方式:引入“包.类”名称-->通过new实例化-->取得实例化对象;
反射方式:实例化对象-->getClass()方法-->得到完整的"包.类"名称
十九、序列化和反序列化
1.主要用于存储对象状态为另一种通用格式,比如存储为二进制、xml、json等等,把对象转换成这种格式就叫序列化,而反序列化通常是从这种格式转换回来。使用序列化主要是因为跨平台和对象存储的需求,因为网络上只允许字符串或者二进制格式,而文件需要使用二进制流格式,如果想把一个内存中的对象存储下来就必须使用序列化转换为xml(字符串)、json(字符串)或二进制(流)
2.序列化的作用是方便存储和传输。
3.序列化通过实现Serializable接口完成。
Serializable这个空接口作用:目的只是简单的标识一个类的对象可以被序列化。
4.实体类实现Serializable接口是一个良好的编程习惯。实现Serializable接口的实体类,一般要求声明一个serialVersionUID成员变量,以表明该实体类的版本。如果实体类结构发生变化,则可以修改serialVersionUID值以支持反序列化的工作。
5.序列化在redis,网络传输中都有所应用。