java学习笔记-基础篇

时间:2022-03-02 19:52:23

Java基础篇

1—12 常识

13 this关键字

14参数传递

16 继承

17 访问权限

28—31异常

1—12 常识

1.文件夹以列表展示,显示扩展名,在地址栏显示全路径

2.javac编译 java运行

3.java开发环境

java编辑器 ( integrated development environment) IDE  集成开发环境

常见的Jbuilder、eclipse

4.double d1,d2,d3=0.123   //不表示d1 d2 d3都是0.123

5.程序执行过程中 对内存的处理  将内存分成4个区域 code segment 、 data segment  、stack  、heap

print和println的区别    println表示此处换行打印

shift+table键的使用 :批量修改缩进/Alt+/开启自动提示

代码不够健壮 只完成了功能 对于用户输入的很多情况没有考虑

方法(method)中的return  代表方法返回  执行到return 表示方法结束

属性 attribute  就是成员变量

哪些类 类的属性和方法 类与类之间的关系

web service和soa  究竟谁赢了(显然是web service赢了)

约定俗称的命名规则:

类名首字母大写   方法名和变量名首字母小写  运用驼峰标识(每个单词首字母大写)

包命名方式   package   公司名称倒过来就行 com.xxx.test

访问控制符 或者叫权限修饰符

继承关键字  extends

人机交互方式:一种是通过图形界面,一种是通过命令行(即cmd)

常用dos命令

dir

cd\  回到根目录

cd. . 回到上级目录

md 文件名    新建目录

cd  目录名    进到指定目录

Java两大核心机制—JVM和GC,有了各平台版本的JVM(如UNIX平台版本、Linux平台版本),java代码在可以一次编译,运行在多个平台上。

10%-3=1  对负数取模可忽略不计,结果仍为正

-10%3=-1  被模的数为负数,结果为负

-10%-3=-1

&&

||   短路与  短路或  如果前边的判断为真或为假  则后边的不进行判断

从键盘读取用户输入,使用Scanner类中的方法:

import java.util.Scanner;  第一步导入Scanner类

public class TestScanner{

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);   第二步声明一个Scanner对象

System.out.println("Please enter number1");

int a;

a = scanner.nextInt();    第三步使用nextInt()方法

}

case 10:

case 9:

10和9这两个标签,可以共用一个代码块

/*

*输入2013年的某个月份和日期,例如month=4 day=21

*经过程序计算,打印出输入的月份和日期是2013年的第几天

*TestSwitch.java

*/

System.out.println();   //直接可以打印换行

break  continue的用法

int[] a =null  数组a的声明

System.out.println(a.length)   在未分配内存空间时 使用数组的属性 会报空指针异常

a=new int[10]  为数组a分配内存空间

多维数组

int  t[][] = new int[4][]

t[0] = new int[5]

t[1] = new int[3]

方法(即函数)中,可以写

return;

但是这行代码之后的代码都不会被执行

类的实例化

Person p = new Person()

p1和p2是Person的两个对象,操作任何一个的(非静态)成员变量都不会对另一个产生影响。

对象的生命周期:

java学习笔记-基础篇

匿名对象

new Person().shout();

出现在:只使用一次,经常将匿名对象作为实参传递给一个函数调用。

信息的封装和隐藏

将属性声明为私有的(private),再提供公开的(public) 方法:getXXX和setXXX方法来操作成员变量。

构造器与类同名且没有返回值(连void都没有)。

方法的重载

在同一个类中允许存在多个同名的方法

方法名不同,返回值类型可以相同也可以不同,参数列表(个数或类型)不一样。

13 this关键字

this是对调用当前方法的那个当前对象的引用

this的用途:指代的是当前对象

1 在一般的方法中可以通过this来引用当前对象的成员(方法、属性)

2 通过this() 调用重载的构造器,需要注意的是,这行代码必须放在重载构造器的第一行。

java学习笔记-基础篇

14参数传递

基本数据类型的参数传递和引用类型的参数传递  两者区分

16 继承

extends关键字

注意:子类不能继承父类私有(private)的成员和方法:不能直接访问。

构造器的继承在Super关键字中讲解。

17 访问权限

Private  仅在类的内部访问

Defalut  仅在包的内部访问

Protected  在子类中该属性可以被访问,可以跨包访问

Public    访问权限最高,无论是否在一个包内,是否是子类,都可以访问

18 方法的重写和覆盖

28 异常

Java运行过程中发生的异常事件可以分为两类:

Error:JVM系统内部错误(无能为力)

Exception:其他因编程错误或偶然的外在因素导致的一般性问题(可以避免),例如:

空指针

访问不存在的文件

网络异常

ArithmeticException:被除数为0的异常

ArrayIndexOutOfBoundsException:数组下边越界异常

ClassCastException:类型转换异常

NullPointerException:空指针异常,引用指向null,但是使用了这个引用的属性或方法

Java采用异常处理机制,将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁易维护。

抓抛模型

抛出(throw)捕获(catch)

一个异常回到main(),main()也不进行处理的话,程序会中止

我们通常可以处理Exception,而对Error无能为力

29 处理异常

try....catch...finally...

在捕获异常时 注意父类参数

可以有多个catch

问题:如果一个语句块中有两种异常,并且也写了两个catch来捕获不同类型的异常,那么这两个catch都会进去吗?还是,有多个catch的情况,只要有一个捕获到了,后边的catch都不进去了?

finally语句始终会被执行

运行时异常和编译时异常

IO异常属于编译时异常

30 声明抛出异常

使用throws关键字声明抛出异常(抛出即不做处理,由调用者处理)

throws方法抛出的异常可以是方法中出现的异常的类型或其父类类型

throws可以声明抛出多个类型的异常,多个异常使用逗号分隔

运行时异常不需要使用throws关键字声明抛出

重写方法不能抛出比重写范围更大的异常

31 人工抛出异常

使用throw关键字,人工手动抛出异常的步骤:

1 创建一个异常类对象

RuntimeException ex = new RuntimeException();

2 把异常类对象抛出去

throw  ex;

自定义的异常类:

1 通常继承自RuntimeException(可以继承Exception)

2 自定义的异常类就是用来被人工抛出的

32 Collection接口

1 创建一个Collection接口的对象

Collection collection = new ArrayList()

2 Collection重要方法说明

2.1 添加

collection.add(new Person())

Collection collection2 = new AyyayList()

collection2.add(new Person())

collection.addall(collection2)

System.out.println(collection.size())

2.2 用于访问集合的方法:

获取集合的长度:size()

对集合进行遍历的方法:iterator()可以得到对应的Iterator接口对象

Iterator:迭代器

获取Iterator接口对象

使用while循环和Iterator对象遍历结合中的每一个元素,具体使用Iterator接口的hasNext()和nex() 方法

Iterrator iterator = collection.iterator()

while(iterator.hasNext()){

Object obj = iterator.next();

System.out.println(obj)

}

2.3 移除集合中的元素

remove():移除某一个指定的对象,通过equals()方法比较集合中是否存在该元素,以及是否能成功移除

removeAll()

clear():使集合中的元素置空

 

2.4 用于检测集合的方法

retains()

retainsAll()

isEmpty()

2.5 其他方法

toArray()

T [] to Array(T[]):涉及到泛型,后面再讲

equals():比较两个集合是否相等

hashCode()

使用增强for循环的方式对集合进行遍历

for(Object obj:collection){

System.out.println(obj)

}

33 Set接口

是collection的子接口,Set集合不允许包含相同元素,比较是否相同使用equals()

HashSet

1.1 基本特征

不能保证元素的排列顺序

HashSet不是线程安全的

集合元素可以是null

对于HashSet:如果两个对象通过equals() 方法返回true,这两个对象的hashcode值也应该相同

LinkedHashSet

按插入顺序排序

34  TreeSet

自然排序和定制排序

自然排序

1 如果使用TreeSet()无参数的构造器创建一个TreeSet对象,则要求放入其中的元素的类必须实现Comparable接口,所以,在其中不能放入null元素

2 必须放入相同类的对象,否则会发生类型转换异常

3 两个对象通过Comparable接口compareTo(Object obj)方法的返回值来比较大小,并进行升序排序

4 当需要把一个对象放入TreeSet中,重写该对象对应的equals()方法时,应保证该方法与compareTo(Object obj)方法有一致的结果

定制排序

1 创建TreeSet对象时,传入Comparator接口的实现类

Set set2 = new TreeSet(comparator); //comparator已经实现了Comparator接口,并重写了其中的compare方法

要求:Comparator接口的compare方法的返回值和两个元素的equals()方法具有一致的返回值

35  List

list有序、可重复

以下为4种排序方法

//iterator遍历

Iterator iterator = list.iterator();

while(iterator.hasNext()){

System.out.println(iterator.next());

}

//for增强遍历

for(Object obj:list){

System.out.println(obj);

}

//for遍历

for(int i = 0 ; i < list.size(); i ++){

System.out.println(list.get(i));

}

//ListIterator遍历

ListIterator lit = list.listIterator();

while(lit.hasNext()){

System.out.println(lit.next());

}

Arrays.asList(new Person("MM",30),new Person("NN",40))

36 Map

Key Value

Key不允许重复

//给map添加元素:put或put(map)

map.put("1", new Person("AA",12));

map.put("1", new Person("BB",25));

map.put("2", new Person("CC",36));

map.put("3", new Person("DD",42));

map.put("4", new Person("EE",68));

/*

//从map中取出元素(遍历)

//先取出键,再根据键取出值

Set keyset = map.keySet();

for(Object key:keyset){

Object value = map.get(key);

System.out.println(key + ":" + value);

}

//直接取出值集合

Collection values = map.values();

for(Object val:values){

System.out.println(val);

}

//直接取出键值对

for(Map.Entry<String, Object> entry:map.entrySet()){

String key = entry.getKey();

Object value = entry.getValue();

System.out.println(key + ":" + value);

}

*/

//移除元素

map.remove("5");

//工具方法:size() contains() isEmpty()

System.out.println(map.size());

System.out.println(map.containsKey("1"));

System.out.println(map.isEmpty());

37 Collections工具类和Enumeration

使用collections的sort方法对List中的元素进行排序

Collections.sort(list, new Comparator(){

public int compare(Object o1, Object o2) {

Person p1 = (Person) o1;

Person p2 = (Person) o2;

return p1.getAge() - p2.getAge();

}

});

}

//获取线程安全的List对象,使用synchronizedList()

List list2 = Collections.synchronizedList(new ArrayList());

//对Enumeration对象进行遍历

Enumeration names = Collections.enumeration(list);

while(names.hasMoreElements()){

Object obj = names.nextElement();

System.out.println(obj);

}

38 泛型

不使用泛型的两个问题:

1 放入集合中的可以是任何类型

2 取出时需要进行强制类型转换

使用泛型 可以解决这个问题 不是任意类型的list  而是一个Person类型的list

List<Person> persons = new ArrayList();

Person [] personArray = persons.toArray(new Person[0]);

Map<String,Person> personMap = new HashMap<String,Person>();

personMap.put("111", persons.get(0));

personMap.put("222", persons.get(1));

personMap.put("333", persons.get(2));

personMap.put("444", persons.get(3));

personMap.put("555", persons.get(4));

for(Map.Entry<String, Person> entry: personMap.entrySet()){

System.out.println(entry.getKey() + ": " + entry.getValue());

}

39 定义泛型

public class Dao<T>{

public T get(Integer id){

T result = null;

return result;

}

public void save(T entity){

}

}

40 继承与泛型

String为Object类型的子类,则String[] 也是Object[] 的子类;

Object [] obj = new String[]{"11","22"};

但,String为Object类型的子类,List<String>并不是List<Object>的子类

List<String> strlist = Arrays.asList("AA","SS");

List<Object> objlist = strlist;

//编译时会提示cannot convert from List<String> to List<Object>

泛型通配符

List<Student> stus = new ArrayList<Student>();

stus.add(new Student("AA",12,"zhengdaUniversity"));

printPersonInfo(stus);

}

public static void printPersonInfo(List<? extends Person> persons){

for(Person person:persons){

System.out.println(person);

}

}

41 泛型方法

把指定类型的数组中的元素放入到指定类型的集合中

泛型方法:在方法声明时,同时声明泛型,在方法的返回值,参数列表以及方法中都可以使用泛型类型

42 枚举类

枚举类:一个类的对象是有限且固定的;因此不能在类的外部创建类的对象;类内部的属性都是常量;在类的内部创建对象,但需要在类的外部能够访问到该对象,而且不能被修改

private Season(String name,String desc){

this.name = name;

this.desc = desc;

}

private final String name;

private final String desc;

public static final Season SPRING = new Season("春天","春风又绿江南岸");

public static final Season SUMMER = new Season("夏天","春风又绿江南岸");

public static final Season FALL = new Season("秋天","春风又绿江南岸");

public static final Season WINTER = new Season("冬天","春风又绿江南岸");

也可以使用enum关键字来定义枚举类

public enum Season2 {

//必须在枚举类的第一行写出有哪些枚举值

SPRING("春天","春天好美啊"),

SUMMER("夏天 ","夏天很美"),

FALL("秋天","秋天很美"),

WINTER("冬天","冬天很冷");

private final String name;

private final String desc;

43 注解

@Override

@Deprecated

@SuppressWarnings

自定义Annotation

1 使用@interface定义注解

2 使用类似于接口方法声明的方式来定义注解的属性;其中返回值为属性的类型,方法名为属性的名称

提取Annotation信息

在反射内容时讲解

44  IO

File类

public class IOTest {

    @Test
public void testFile() throws IOException {
//新建一个文件对象,该文件应已被创建
File file = new File("hello.txt");
//访问文件的名字
String name = file.getName();
System.out.println(name);
//访问文件的绝对路径
String path = file.getAbsolutePath();
System.out.println(path);
//将文件剪切到其他地方
// file.renameTo(new File("d:\\hello.txt"));
//文件监测相关方法
System.out.println(file.exists());
File dir = new File("HaHa"); //新建目录对象,该目录应事先已创建
System.out.println(dir.isFile()); //获取文件的常规信息
System.out.println(file.length()); //文件操作
File file2 = new File("abcd.txt"); //新建文件
file2.createNewFile();
} }

还可以通过mkDir()方法新建目录

IO流的分类

InputStream&Reader

InputStream和Reader是所有输入流的基类

    @Test
public void testInputStream() throws IOException {
//创建一个字节输入流
InputStream in = new FileInputStream("hello.txt");
//读取文件内容
//.1读取一个字节,效率很低 -1表示读到文件结尾
// int result = in.read();
// while(result != -1){
// System.out.print((char)result);
// result = in.read();
// } //.2一次读取一组字符
byte [] buffer = new byte[10];
int len = 8; //返回读取的字节数,若为-1表示读到文件的结尾
// while((len = in.read(buffer)) != -1){
// //这样读 可能会出现错误 有可能最后不够8个字符
//// for(byte b:buffer){
// //这样读可以避免以上错误
// for(int i = 0; i < len; i++){
// System.out.print((char)buffer[i]);
// }
// } //.3 把内容读取到字节数组的部分连续的元素中
byte [] result = new byte[1024*10];
//2表示读取in这个字节流从头开始的2个字符,result是被读取后存放字节的数组,0表示从result的起始位置开始存放
in.read(result, 0, 2);
for(int i = 0; i < result.length; i++){
System.out.print((char)result[i]);
}
    
    in.close(); //关闭流文件
     
  }
@Test
public void testReader() throws IOException {
Reader reader = new FileReader("hello.txt"); char[] buffer = new char[10];
int len = 10; while((len = reader.read(buffer)) != -1){
for(int i = 0 ;i < len; i++){
System.out.print(buffer[i]);
}
} reader.close(); }

OutputStream&文件复制

OutputStream和Writer,是所有输出流的基类

@Test
public void testOutputStream() throws IOException {
//输出字节流 abcd.txt应已经创建
OutputStream out = new FileOutputStream("abcd.txt");
//需要写入的字符
String content = "www.test.com.hahahahhahah.hahahah.hahahhahahhahahahahhahahahhahahah"; byte[] buffer = new byte[10]; //这里的buffer只声明了10个字节,但发现可以容纳任意字节
//将字符转换成字节
buffer = content.getBytes();
//下面的写法也可以
// for(int i = 0 ; i < buffer.length; i++){
// out.write(buffer[i]);
// }
//直接这样就可以写入
out.write(buffer);
//写入一部分字符
out.write(buffer, 0, 10); out.close(); }
/*
* 利用字节输入输出流,完成hello.txt文件的复制,将该文件复制为hello2.txt
* 除文本文件外,还可以复制二进制文件;字符流只能处理文本文件
* */
@Test
public void testCopyFile() throws IOException {
//.1创建定位到hello.txt的文件输入流
InputStream in = new FileInputStream("hello.txt");
//.2创建定位到hello2.txt的文件输出流
OutputStream out = new FileOutputStream("hello2.txt");
//.3创建一个byte数组,用于读写文件
byte [] buffer = new byte[1024*10];
int len = 0;
//.4读写文件
while((len = in.read(buffer)) != -1){
out.write(buffer,0,len);
}
//.5关闭流资源
in.close();
out.close();
}
利用字符输入输出流,完成hello.txt文件的复制,将该文件复制为hello2.txt
public class IOTest2 {
@Test
public void testCopyFile() throws IOException {
//.1 声明输入输出流
Reader in = new FileReader("hello.txt");
Writer out = new FileWriter("hello2.txt"); //.2 创建一个字符数组
char [] buffer = new char[10]; //.3 利用循环读取源文件,并向目标文件写入
//.4 注意使用的写入方法:write(cbuf, off, len)
//而不能直接使用write(cbuf)
int len = 0;
//in.reader()返回读取到的字符的个数,到达结尾时返回-1
while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
} //.5 关闭流资源
in.close();
out.close(); }
}

缓冲流

BufferedInputStream和BufferedOutputStream

BufferedReader和BufferedWriter

/*
* 复制hello.txt到hello3.txt*/
@Test
public void testBufferedReaderAndBufferedWriter() throws IOException{
//.1 创建BufferedReader和BufferedWriter
Reader in = new FileReader("hello.txt");
BufferedReader bufferedReader = new BufferedReader(in); Writer out = new FileWriter("hello3.txt");
BufferedWriter bufferedWriter = new BufferedWriter(out); //.2 进行读写操作
String buffer = null; int i = 0 ; while((buffer = bufferedReader.readLine()) != null){
if (i != 0) {
bufferedWriter.write("\n");
}
bufferedWriter.write(buffer);
i++;
} //.3 关闭流:只需要关闭包装流,节点流会会在内部关闭
bufferedReader.close();
bufferedWriter.close();
}
    /*
* 利用BufferedInputStream和BufferedOutputStream完成
* hello.txt到hello4.txt的复制*/
@Test
public void testBufferedInputStreamAndBufferedOutputStream() throws IOException{
InputStream inputStream = new FileInputStream("hello.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
OutputStream outputStream = new FileOutputStream("hello4.txt");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); byte [] buffer = new byte[10];
int len = 0 ; while((len = bufferedInputStream.read(buffer)) != -1){
bufferedOutputStream.write(buffer, 0, len);
} bufferedInputStream.close();
bufferedOutputStream.close();
}

转换流

InputStreamReader和OutputStreamWriter

    /*
* 利用转换流InputStreamReader*/
@Test
public void testInputStreamReader() throws IOException{
//指向文档的字节流
InputStream in = new FileInputStream("hello.txt");
//把上面的流转换为字符流
Reader reader = new InputStreamReader(in);
//把字符流转换为带缓冲的字符流
BufferedReader bufferedReader = new BufferedReader(reader); String str = null;
while((str = bufferedReader.readLine()) != null){
System.out.println(str);
} //关闭
in.close();
reader.close();
bufferedReader.close();
}
    /*
* 先创建两个字节输入输出流:分别指向:hello.txt hello5.txt
* 然后再转为字符输入输出流
* 再转为带缓冲的字符输入输出流
*
* 完成文件的复制*/
@Test
public void testOutputStreamWriter() throws IOException{
InputStream in = new FileInputStream("hello.txt");
OutputStream out = new FileOutputStream("hello5.txt"); Reader reader = new InputStreamReader(in);
Writer writer = new OutputStreamWriter(out); BufferedReader bufferedReader = new BufferedReader(reader);
BufferedWriter bufferedWriter = new BufferedWriter(writer); String buffer = null;
int i = 0; while((buffer = bufferedReader.readLine()) != null){
if (i != 0) {
bufferedWriter.write("\n");
}
bufferedWriter.write(buffer);
i++;
} bufferedReader.close();
bufferedWriter.close();
}

对象流

ObjectInputStream和ObjectOutputStream

.1)序列化需要实现Serializable接口

.2)类A下的某个字段是引用类型,引用的是类B,则类B必须实现Serializable接口,否则类A不能被序列化

在实际开发中,框架中已包含了此部分代码,不需要我们自己写

public class Person implements Serializable {

    /**
* 类的版本号,用于对象的序列化,具体用于读取对象时比对硬盘上对象的版本和
* 程序中对象的版本是否一致,若不一致读取失败,并抛出异常
*/
private static final long serialVersionUID = 1L;
往硬盘文件写内容
@Test
public void testSerializable() throws IOException {
Person person = new Person("Lily",26); OutputStream outputStream = new FileOutputStream("hello.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream); objectOutputStream.writeObject(person); outputStream.close();
objectOutputStream.close();
}
从硬盘文件读取    
@Test
public void testOnjectInputStream() throws IOException, ClassNotFoundException {
InputStream inputStream = new FileInputStream("hello.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream); Object obj = objectInputStream.readObject();
System.out.print(obj); objectInputStream.close();
inputStream.close(); }

 RandomAccessFile类

RandomAccessFile及可以读取文件内容,也可向文件输入内容

@Test
public void testRandomAccessFile() throws IOException {
//.1创建一个RandomAccessFile对象
RandomAccessFile randomAccessFile = new RandomAccessFile("hello.txt", "rw");
//.3读取文件内容
String str = null;
while((str = randomAccessFile.readLine()) != null){
System.out.println(str);
}
//设置指针位置,会覆盖从指针开始位置的待增加字符串长度的字符
randomAccessFile.seek(10);
//.4向文件写内容 在文件结尾增加字符串
randomAccessFile.writeBytes("append...");
//.2关闭RandomAccessFile对象
randomAccessFile.close();
}
/*
* 向hello.txt文件中插入一行:www.baidu.com
* 插入到第二行,原内容下移*/
@Test
public void testRandomAccessFile() throws IOException {
RandomAccessFile access = new RandomAccessFile("hello.txt", "rw");
//先读一行
String line = access.readLine();
//这里有疑问,怎么能确保读到buffer中的是除第一行之外的字符呢?又
//没有将指针定位到第一行结尾
byte[] buffer = new byte[(int)(access.length()-line.length())];
access.read(buffer); access.seek(line.length());
//写入要写的字符
access.writeBytes("\nHH\n");
//再写入先前的内容
access.write(buffer);
access.close();
}

45 Java常用类

1 String是不可变的字符序列

2  关于字符串缓冲池:直接通过=为字符串赋值,会先在缓冲池中查找有没有一样的字符串,如果有就把那个引用赋给字符串变量,否则,会创建一个新的字符串,并把它放入缓冲池

3 字符串的几个常用方法:

3.1 去除前后空格的trim()方法

3.2 求子字符串的方法:subString()

从fromIndex开始,包含fromIndex,且String的字索引从0开始

3.3 subString(fromIndex,toIndex):[fromIndex,toIndex)

3.4 indexOf:求指定字符的索引

3.5 spilt(String regex):把字符串拆分成字符数组

3.6 equals():比较字符串内容是否相等必须使用该方法,不能直接使用==

StringBuffer和StringBuilder

StringBuffer和StringBuilder是可以被修改的字符序列

append()方法:追加字符

注意:append()方法的返回值还是当前的StringBuffer对象,可以使用方法的连缀

StringBuilder.append("a")

.append("b")

.append("c")

2). StringBuffer, StringBuilder 是可变的字符序列.

> StringBuffer 是线程安全的, 所以效率较低.

> StringBuilder 是线程不安全的, 效率较高. 大部分时使用 StringBuilder.

Date()封装了日期和时间

1. DateFormat是一个抽象类

抽象类获取对象的方式:

1) 创建其子类对象

2) 有的抽象类中提供了静态工厂方法来获取抽象类的实例

-SimpleDateFormat

如果需要把 Date 类型的对象格式化为一个字符串, 或把一个字符串转为一个 Date 对象则使用 DateFormat.

//1. 调用静态工厂方法来获取 DateFormat 对象.

//传入的参数是日期或时间的样式.

DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,

DateFormat.LONG);

Date date = new Date();

//格式化日期对象的 format 方法

String dateStr = dateFormat.format(date);

System.out.println(dateStr);

dateStr = "2013年6月10日 下午03时48分06秒";

//解析字符串到日期对象的 parse 方法.

Date date2 = dateFormat.parse(dateStr);

System.out.println(date2);

//创建 SimpleDateFormat 对象.

DateFormat dateFormat =

new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

Random和Math

Random中封装了随机相关的方法:返回随机的基本数据类型的值

Math:中封装了常用的数学方法

小结

4. 集合:

1). Collection
①. List:
②. Set:

2). Map:
3). Iterator:
4). Collections, Arrays:

3. 泛型:

1). 在集合中使用泛型: List<Person> persons = new ArrayList<>();
2). 定义泛型类: class Dao<T, PK>{}. 在泛型类中可以像使用其他类型那样使用泛型类型.
3). 泛型和继承:
①. List<Object> 不是 List<Person> 的父类!
②. 通配符: List<? extends Object> list 可以指向 List<Object> 或 List<Person>
注意: 带有通配符的泛型集合中不能添加除 null意外的任何元素.
4). 定义泛型方法: public static <E> E get(E e, Integer id){...}

2. IO:

1). 类:

InputStream FileInputStream BufferedInputStream ObjectInputStream
OutputStream FileOutputStream BufferedOutputStream ObjectOutputStream
Reader FileReader BufferedReader InputStreamReader
Writer FileWriter BufferedWriter OuputStreamWriter

2). 最常用的方法:

①. 文件的复制.

InputStream in = new FileInputStream(fileName);
OutputStream out = new FileOutputStream(fileName2);

byte [] buffer = new byte[1024 * 10];
int len = 0;

while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
}

in.close;
out.close;

②.

BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));

3). 序列化:
①. 序列化的意义:
②. 如果需要对某个类的对象实现序列化: 则该类需要实现 Serializable 接口. 且该类的所有字段也必须
是可被序列化的.

4). RandomAccessFile: 类中有一个指向文件内容的指针. 通过 seek() 方法来移动指针.
可以完成对文件的读写操作.

1. 关于常用类:

1). String 是一个不可变的字符序列!
2). StringBuffer, StringBuilder 是可变的字符序列.
> StringBuffer 是线程安全的, 所以效率较低.
> StringBuilder 是线程不安全的, 效率较高. 大部分时使用 StringBuilder.
3). Date: 封装了时间和日期.
4). DateFormat
-SimpleDateFormat
如果需要把 Date 类型的对象格式化为一个字符串, 或把一个字符串转为一个 Date 对象
则使用 DateFormat.

//1. 调用静态工厂方法来获取 DateFormat 对象.
//传入的参数是日期或时间的样式.
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.LONG);

Date date = new Date();
//格式化日期对象的 format 方法
String dateStr = dateFormat.format(date);
System.out.println(dateStr);

dateStr = "2013年6月10日 下午03时48分06秒";
//解析字符串到日期对象的 parse 方法.
Date date2 = dateFormat.parse(dateStr);
System.out.println(date2);

//创建 SimpleDateFormat 对象.
DateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

5). Random & Math

46 反射

一般在框架中会使用到反射

有3种方式可以得到Class对象

/**
* 关于Class:
* 1.Class是一个类
* 2.对象照镜子后可以得到的信息,某个类的数据成员名、方法和构造器
* 某个类到底实现了哪些接口
* 3.对于每个类而言,JRE都为其保留一个不变的Class类型的对象
* 4.一个Class对象只能由系统建立对象
* 5.一个类在JVM中只会有一个Class实例
* @throws ClassNotFoundException
*
*/ @Test
public void testClass() throws ClassNotFoundException{
Class clazz = null; //1.得到Class对象
//1.1直接通过类名.class的方式得到
clazz = Person.class; //1.2 通过对象调用getClass()方法来获取
Person person = new Person();
clazz = person.getClass(); //1.3 通过全类名的方式获取,用的较多
String className = "com.test.lesson12.Person";
clazz = Class.forName(className); }
/**
* Class类的newInstance()方法
*
*/
@Test
public void testNewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String className = "com.test.lesson12.Person";
Class clazz = Class.forName(className); //利用Class对象的newInstance()方法来创建类的一个对象
//实际调用的是Person类的无参数的构造器,在声明类的时候无参数的构造器是必要的
//一般一个类若声明了有参数的构造器,还应声明一个无参数的构造器
Object obj = clazz.newInstance(); }

类加载器

@Test
public void testClassLoader() throws ClassNotFoundException{ String className = "com.test.lesson12.Person";
//1.获取一个系统的类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader); //2.获取系统类加载器的父加载器
classLoader = classLoader.getParent();
System.out.println(classLoader); //3. 获取扩展类加载器的父加载器
classLoader = classLoader.getParent();
System.out.println(classLoader); //4.测试当前类由哪个类加载器进行加载
classLoader = Class.forName(className).getClassLoader();
System.out.println(classLoader); //5.测试JDK提供的Object类由哪个类加载器负责加载
classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader); //6.关于类加载器的一个主要方法
//调用getResourceAsStream获得类路径下的文件对应的输入流
InputStream in = null;
in = this.getClass().getClassLoader().getResourceAsStream("com/test/lesson12/test.properties");
System.out.println(in);
}

method:

/*Class是一个对类的描述
* Method:指定类中的方法
* 1.获取Method
* 1.1获取类的方法的数组:clazz.getDeclaredMethods()
* 1.2获取类的指定的方法:
* clazz.getDeclaredMethod("setName", String.class)
* 方法名 方法的参数类型列表
*
* 1.3通过method对象执行方法:
* Object obj = clazz.newInstance();
method.invoke(obj, "设置的name");
*
* */
@Test
public void testMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String className = "com.test.lesson12.Person";
Class clazz = Class.forName(className); //1.clazz对应的Person类的方法,但不能获取private方法
Method[] methods = clazz.getMethods();
for (Method method:methods) {
System.out.println(method.getName());
} //2.获取类对象的所有方法,包括private方法,且只获取当前类声明的方法
Method[] methods2 = clazz.getDeclaredMethods();
for (Method method:methods2) {
System.out.println(method.getName());
} //3.获取指定的方法
Method method = clazz.getDeclaredMethod("setName", String.class); //1个String类型的参数
System.out.println(method); Method method2 = clazz.getDeclaredMethod("test"); //无参数的private方法
System.out.println(method2); Method method3 = clazz.getDeclaredMethod("setName", String.class,Integer.class);// 两个参数
System.out.println(method3); //4.执行方法
Object obj = clazz.newInstance();
method.invoke(obj, "设置的name");
}

其余小节未细看:

3). 尚硅谷_佟刚_Java基础_ 反射_获取并执行父类中定义的私有方法

4). 尚硅谷_佟刚_Java基础_反射_使用 Method 的工具方法、

5). 尚硅谷_佟刚_Java基础_ 反射_Field

47 线程

获取当前线程:Thread.currentThread().getName()

/*
* 1 在Java中,Thread类代表一个线程
*
* 2.实现线程有2种方式:
* 2.1继承Thread类
* 2.2实现Runnable接口
*
* 3.继承Thread类:
* 3.1必须重写run()方法,里边放置的实际的线程体
*
* 4.启动线程:
* 4.1创建Thread对象
* 4.2 调用Thread对象的start()方法启动线程,而不是run()方法
*
* 5 实现Runnable接口的方式:
* 5.1创建实现Runnable接口的实现类:必须实现run()方法
* 5.2创建5.1对应的Runnable接口的实现类对象
* 5.3创建Thread对象,利用Thread(Runnable target)
* 5.4 调用Thread类的start()方法启动线程
*
* */ public class threadTest { public static void main(String[] args) {
Thread thread = new FirstThread();
thread.start(); String threadName =
Thread.currentThread().getName();
for (int i = 0; i < 100; i++) {
System.out.println(threadName + ":" + i);
} } } class FirstThread extends Thread{
/*线程体在run()方法中*/
@Override
public void run() {
String threadName =
Thread.currentThread().getName();
for (int i = 0; i < 100; i++) {
System.out.println(threadName + ":" + i);
}
}
}

以下三种方式实现:使用两个线程共同打印1—100

/*不考虑线程安全的问题:
* 使用Thread类,创建两个线程,共同打印0——99
* */ public class PrintNumber { public static void main(String[] args) { int i = 0; MyThread thread1 = new MyThread("Thread1");
MyThread thread2 = new MyThread("Thread2"); MyThread.setI(i); thread1.start();
thread2.start(); } } class MyThread extends Thread{
//给线程创建一个静态参数
private static int i; public static void setI(int i) {
MyThread.i = i;
} public MyThread(String threadName) {
super(threadName);
} @Override
public void run() {
String threadName = Thread.currentThread().getName(); for (; i < 100; i++) {
System.out.println(threadName + ":" + i);
}
}
}
public class PrintNumber2 {
int i = 0 ; public static void main(String[] args) {
PrintNumber2 printNumber = new PrintNumber2(); MyThread2 thread1 = new MyThread2("thread1", printNumber);
MyThread2 thread2 = new MyThread2("thread2",printNumber); thread1.start();
thread2.start(); } } class MyThread2 extends Thread{
PrintNumber2 printNumber; public MyThread2(String threadName,PrintNumber2 printNumber) {
super(threadName);
this.printNumber = printNumber;
} @Override
public void run() {
String threadName = Thread.currentThread().getName(); for (; printNumber.i < 100; printNumber.i++) {
System.out.println(threadName + ":" + printNumber.i);
}
}
}
public class MyRunnable implements Runnable {

    int i = 0;
public void run() {
String threadName = Thread.currentThread().getName(); for (; i < 100; i++) {
System.out.println(threadName + ":" + i);
}
} public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable(); Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnable); thread1.start();
thread2.start(); } }

 线程的生命周期

New(新建状态) Runnable(可执行状态,有权获得CPU控制权,正在等待) Running(执行状态,已获得CPU控制权)

Dead(死亡状态,使用isAlive方法判断是否死亡,已经死亡的线程不能再调用start()方法,否则会抛异常)

1)yield()方法 主动让出CPU控制权 回到等待状态

2)sleep(int mills)方法  使线程休眠一段时间 以ms为单位

3) join()方法 当前线程调用其他线程的join方法,当前线程将被挂起,进入阻塞状态,等待另一个线程执行完毕

4)interrupt()  解除线程的阻塞状态 会抛出InterruptedException

5)isAlive()

线程调度

1)线程的优先级

setPriority() (一般不使用这种方法来进行优先级设置)getPriority()

共有10个优先级 整数值越大优先级越高 每个线程都有1个默认优先级 主线程的优先级是5

3个常量:MIN_Priority  MAX_Priority  NORM_Priority

线程同步

实现如下效果:

小强 拿走了1个苹果
还剩下4个苹果
小强 拿走了1个苹果
还剩下3个苹果
小明 拿走了1个苹果
还剩下2个苹果
小强 拿走了1个苹果
还剩下1个苹果
小强 拿走了1个苹果
还剩下0个苹果
小强 的线程结束了
小明 的线程结束了

public class ThreadTest2 implements Runnable {

    int appleNum = 5;

    public static void main(String[] args) throws InterruptedException {
ThreadTest2 threadTest2 = new ThreadTest2(); Thread th1 = new Thread(threadTest2);
Thread th2 = new Thread(threadTest2); th1.setName("小强");
th2.setName("小明"); th1.start();
th2.start(); } boolean getApple(){
//将以下代码锁起来,同一时刻只允许一个线程使用
synchronized (this) {
if(appleNum > 0){
System.out.println(Thread.currentThread().getName() + " 拿走了1个苹果");
appleNum = appleNum - 1;
System.out.println("还剩下" + appleNum + "个苹果");
return true;
} return false;
} } public void run() {
while(appleNum > 0){
getApple();
} if(getApple() == false){
System.out.println(Thread.currentThread().getName() + " 的线程结束了");
}
} }

线程安全问题

1)多个线程使用同一个资源导致,使用synchronized代码块(称为同步块)解决线程安全的问题

2)也可以使用synchronized 关键字定义方法,称为同步方法

线程通信

1)wait()方法

2)notify()  notifyAll()方法 唤醒等待中的线程 这些方法都需要在同步方法中调用

/*
* 张飞有1张20元钞票 刘备和关羽各有1张5元钞票 售货员已有1张5元钞票 票值5元
* */ public class TicketHouse implements Runnable{ private int fiveCount = 1;
private int twyCount;
public synchronized boolean buyticket(){ //该方法使用synchronized修饰
String buyerName = Thread.currentThread().getName();
if("zf".equals(buyerName)){
if(fiveCount < 3){
System.out.println("张飞来买票了,当前的五元钞票已有" + fiveCount + "张,不够找零,请您等待");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("张飞来买票了,当前的五元钞票已有" + fiveCount + "张");
fiveCount = fiveCount -3 ;
twyCount = twyCount + 1;
System.out.println("卖给张飞一张票,目前五元钞票剩下" + fiveCount + "张;目前二十元钞票有" + twyCount + "张");
}else if("gy".equals(buyerName)){
System.out.println("关羽来买票了,当前的五元钞票已有" + fiveCount + "张");
fiveCount = fiveCount + 1;
System.out.println("卖给关羽一张票,目前五元钞票剩下" + fiveCount + "张");
}else if("lb".equals(buyerName)){
System.out.println("刘备来买票了,当前的五元钞票已有" + fiveCount + "张");
fiveCount = fiveCount + 1;
System.out.println("卖给刘备一张票,目前五元钞票剩下" + fiveCount + "张");
} if(fiveCount == 3){
notifyAll(); //唤醒被暂停的线程,执行wait()后的代码
} return false;
} public void run() {
buyticket();
} public static void main(String[] args) {
TicketHouse ticketHouse = new TicketHouse(); Thread th1 = new Thread(ticketHouse);
Thread th2 = new Thread(ticketHouse);
Thread th3 = new Thread(ticketHouse); th1.setName("zf");
th2.setName("gy");
th3.setName("lb"); th3.start();
th2.start();
th1.start();
} }

 48 网络编程

目的:直接或间接地通过网络协议与其他计算机进行通讯

网络编程中主要有两个问题:

1)如何准确地定位网络上一台或多台主机

2)找到主机后如何可靠高效地进行数据传输

常用的TCP/IP以其中的两个协议:TCP和IP协议而得名,实际上是一组协议,还包括其他一些协议

传输控制协议TCP:先建立TCP链接,在传输完毕后,释放连接

用户数据包协议:UDP

端口号与IP地址和组合发出一个网络套接字(Socket) 端口号被规定为一个16位的整数0—65535

套接字能执行7种基本操作:

—连接到远程主机

—绑定到端口

—接收从远程机器来的连接请求

—监听到达的数据

—发送数据

—接收数据

—关闭连接

@Test
public void testInetAddress() {
InetAddress inetAddress;
try {
//使用getByName()方法
inetAddress = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress);
} catch (UnknownHostException e) {
System.out.println("这个域名不存在");
e.printStackTrace();
} }

客户端Socket的工作过程包括4个步骤:

1)创建一个Socket

2)打开连接到Socket的输入/出流

3)按照一定协议对Socket进行读/写操作

4)关闭Socket

服务端Socket的工作过程包含4个步骤:

1)调用ServerSocket(int port)创建一个服务器端套接字,并绑定到指定端口上

2)调用accept(),监听连接请求

3)调用Socket类的OutputStream和getInputStream获取输出流和输入流,开始网络数据的发送和接收

4)关闭Socket

Server端代码:

@Test
public void testServerSocket() throws IOException {
ServerSocket serverSocket = new ServerSocket(8989);
Socket socket = serverSocket.accept(); OutputStream out = socket.getOutputStream();
PrintWriter writer = new PrintWriter(out);
writer.write("来自服务端的问候哦"); writer.close();
out.close(); socket.close();
serverSocket.close(); }

客户端代码:

@Test
public void testSocket() throws IOException {
InetAddress address = InetAddress.getByName("127.0.0.1");
Socket socket = new Socket(address, 8989); InputStream in = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in)); System.out.println("O(∩_∩)O:" + reader.readLine()); reader.close();
in.close();
socket.close(); }

完成将服务器文件复制到本地:

public class SocketTest {

    @Test
public void testServerSocket() throws IOException {
//新建一个ServerSocket,并设置监听请求
ServerSocket serverSocket = new ServerSocket(8686);
Socket socket = serverSocket.accept();
//从程序到socket的输出流
OutputStream out = socket.getOutputStream();
//buffer用于存放从文件中读取出来的字符
byte [] buffer = new byte[1024];
int len = 0;
//从文件到程序的输入流
InputStream in = new FileInputStream("abc.jpg");
//通过in从文件读入buffer,再从buffer通过out写入socket,客户端会通过socket接收
while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
} in.close();
out.close();
socket.close();
serverSocket.close(); } @Test
public void testSocket() throws IOException {
//客户端新建一个socket并绑定端口
InetAddress address = InetAddress.getByName("127.0.0.1");
Socket socket = new Socket(address, 8686);
//从socket到程序
InputStream in = socket.getInputStream();
//buffer用于存放从程序到本地文件
byte [] buffer = new byte[1024];
int len = 0 ;
//从程序到本地文件
OutputStream out = new FileOutputStream("abcd.jpg");
//通过in从socket读入buffer,再通过out将buffer写入文件
while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
} in.close();
out.close();
socket.close();
} }

UDP:不能保证数据是否能送达,也不能保证数据什么时候能送达,所以不建议使用

URL编程:

/*
* 将网络资源下载到本地
* */
@Test
public void testUrlConnection() throws IOException {
URL url = new URL("http://127.0.0.1:8080/examples/test.txt"); System.out.println(url.getPath()); URLConnection urlConnection = url.openConnection(); //将文件下载到本地
InputStream in = urlConnection.getInputStream();
OutputStream out = new FileOutputStream("text.txt"); byte [] buffer = new byte[1024];
int len = 0; while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
}
}

至此,java基础篇结束。