1.弄懂 JRE、JDK、JVM 之间的区别与联系
JVM :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心,具体的下文会详细说明。
JRE :英文名称(Java Runtime Environment),我们叫它:Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
JDK :英文名称(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
显然,这三者的关系是:一层层的嵌套关系。JDK>JRE>JVM。
2.Java 为什么能跨平台,实现一次编写,多处运行?
Java 能够跨平台运行的核心在于 JVM 。不是 Java 能够跨平台,而是它的 jvm 能够跨平台。我们知道,不同的操作系统向上的 API 肯定是不同的,那么如果我们想要写一段代码调用系统的声音设备,就需要针对不同系统的 API 写出不同的代码来完成动作。
而 Java 引入了字节码的概念,jvm 只能认识字节码,并将它们解释到系统的 API 调用。针对不同的系统有不同的 jvm 实现,有 Linux 版本的 jvm 实现,也有 Windows 版本的 jvm 实现,但是同一段代码在编译后的字节码是一样的。引用上面的例子,在 Java API 层面,我们调用系统声音设备的代码是唯一的,和系统无关,编译生成的字节码也是唯一的。但是同一段字节码,在不同的 jvm 实现上会映射到不同系统的 API 调用,从而实现代码的不加修改即可跨平台运行。
1.数 据 类 型
(1)基本类型(8种)
整数类型:byte(8位), short(16位), int(32位), long(64位)
浮点类型:float(32位), double(64位)
字符类型:char(16位)
布尔类型:boolean
(2)复合类型
class(类)
interface(接口)
数组
2.类型转换
3.逻辑表达式(布尔值,不能是int等)
4.switch(expression)中的expression新版本类型都可以
5.break lab; 跳出多重循环
1.对象互发消息
(1)引用必须引用了特定的对象,否则会在运行时抛出NullPointerException异常
(2)对象必须定义了相应的属性或方法,否则编译不会通过
(3)被访问的属性或方法具有可访问的权限
2.区别对象和对象引用
(1)创建对象:
new IntClass();
对象分配在堆上。
(2)声明一个对象引用:
IntClass ic;
对象引用分配在栈上。
(3)初始化对象引用:
ic = new IntClass();
例1:
对象内存空间分布:
IntClass ic = new IntClass();
实质是将创建的IntClass对象的地址赋给对象引用ic,从此ic与该对象关联,通过ic即可操纵该对象。
例2:
对象作为参数的特点:
普通数据类型作为参数传递是值传递,而对象是引用传递。
public class Test{
private static int a;
public static void main(String [] args){
modify(a);
System.out.println(a);
}
public static void modify(int a){
a++;
}
}
本程序输出为0,因为a++是对形式参数进行自增,而不是类属性 a进行自增。
例3:
对象的引用传递举例:
对象是引用传递,当对象作为参数传递时,传递的是对象的地址。
class IntClass{
int value;
}
public class test {
private static int a;
public static void main(String [] args){
IntClass a = new IntClass();
modify(a,8);
System.out.println(a.value);
}
public static void modify(IntClass s, int val){
s.value = val;
}
}
输出:8
3.区别Java和C++
Java :只有当你使用 new 操作符时,才会真正在内存中申请一块空间,创建一个新对象,并将该对象绑定到你所定义的变量名上。其它情况下,要么是将已有对象绑定到某个变量名上,要么就是定义的变量名是个空引用,没有绑定任何对象。
也就是说,定义变量名只是创建了一个新的标识符,跟创建对象没有关系,创建对象必须通过 new 来完成,只有创建对象时才会申请内存空间。
C++ :当你定义了一个变量 s 时,即使你没有给它赋值,也意味着你不但创建了一个新的标识符,同时还在栈中申请了对应的内存空间。
因此,C++ 中定义的变量名不仅仅是个标识符,还自动关联着栈中的一块内存空间。
而 C++ 中的 new 操作符表示的是在堆中申请内存,因为栈中的内存在运行时期大小是固定且有限的,因此需要动态内存分配的时候就需要用 new 来实现。这类似于 C 里面的 malloc 函数,只不过 new 操作符还封装了其它的操作。
总结而言,Java 中的变量名仅仅是一个用于引用内存中实际对象的标识符,如果你没给它关联对象,它就为空引用。而 C++ 中的变量名(非指针类型),虽然也是标识符,但却始终关联着实际的内存空间,当我们看到一个变量(非指针类型)时,就知道它代表着一块实际的内存空间。
4.创建数组(数组是对象)
1.一维数组
A.声明
(1)int
int[] test_int;
(2)String
String[] test_String;
(3)自定义类
MyClass[] test_mc;
(4)对象数组
Integer[] test_Integer;
B.初始化
a.使用关键字new进行定义
类型标识符[] 数组名 = new 类型标识符[数组长度];
(1)int
产生一个具有10个单元,类型为 int 的数组对象,所有单元的初值为0
int[] test_int = new int[10];
或
int[] test_int;
test_int = new int[10];
(2)String
产生一个具有10个单元,类型为 String 的数组对象,所有单元的初值为null
String[] test_String = new String[10];
或
String[] test_String;
test_String = new String[10]; // 注意:不要写成 new String(10)
(3)自定义类
产生一个具有10个单元,类型为 MyClass 的数组对象,所有单元的初值为null
MyClass[] test_mc = new MyClass[10];
或
MyClass[] test_mc;
test_mc = new MyClass[10];
(4)对象数组
产生一个具有10个单元,类型为 Integer 的数组对象,所有单元的初值为null
Integer[] test_Integer = new Integer[10];
或
Integer[] test_Integer;
test_Integer = new Integer[10];
b. 直接在声明的时候进行初始化
注意:这种定义方式只能在一行代码中,不能分开。
(1)int
int[] test_int = {1,2,3};
(2)String
或
String[] test_String = {"ab","cd","ef"};
或
String[] test_String = {new String("ab"),new String("cd"),new String("ef")};
(3)自定义类
MyClass test_mc1 = new MyClass();
MyClass test_mc2 = new MyClass();
MyClass test_mc3 = new MyClass();
MyClass[] test_mc = {test_mc1,test_mc2,test_mc3};
(4)对象数组
Integer[] test_Integer = {3,5};
或
Integer[] test_Integer = {new Integer(3), new Integer(5)};
c. 采用如下方法定义及初始化
(1)int
(2)String
String[] test_String = new String[] {“ab”,“cd”,“ef”};
或
int[] test_int = new int[] {1,2,3};
(2)String
或
String[] test_String = new String[] {"ab","cd","ef"};
或
String[] test_String = new String[] {new String("ab"), new String("cd"), new String("ef")};
(3)自定义类
(4)对象数组
Integer[] test_Integer = new Integer[] {1,2,3};
或
MyClass test_mc1 = new MyClass();
MyClass test_mc2 = new MyClass();
MyClass test_mc3 = new MyClass();
MyClass[] test_mc = new MyClass[] {test_mc1,test_mc2,test_mc3};
(4)对象数组
或
Integer[] test_Integer = new Integer[] {1,2,3};
或
Integer[] test_Integer = new Integer[] {new Integer(1), new Integer(2), new Integer(3)};
C.使用foreach语句遍历一维数组
(1)int
public class MyClass {
public static void main(String[] args) {
int[] test_int = new int[10];
test_int[0] = 1;
for(int x: test_int) {
System.out.println(x + " ");
}
}
}
输出:1 0 0 0 0 0 0 0 0 0
(2)String
public class MyClass {
public static void main(String[] args) {
String[] test_String = {"ab","cd","ef"};
for(String x: test_String) {
System.out.print(x + " ");
}
}
}
输出:ab cd ef
(3)自定义类
public class MyClass {
public int value = 1;
public static void main(String[] args) {
MyClass test_mc1 = new MyClass();
MyClass test_mc2 = new MyClass();
MyClass test_mc3 = new MyClass();
MyClass[] test_mc = {test_mc1,test_mc2,test_mc3};
for(MyClass x: test_mc) {
System.out.print(x.value + " ");
}
System.out.println();
for(MyClass x: test_mc) {
System.out.print(x + " ");
}
}
}
输出:1 1 1
test . MyClass@15db9742 test. MyClass@6d06d69c test . MyClass@7852e922
(4)对象数组
public class MyClass {
public int value = 1;
public static void main(String[] args) {
Integer[] test_Integer = {new Integer(3), new Integer(5)};
for(Integer x: test_Integer) {
System.out.print(x + " ");
}
}
}
输出:3 5
2.二维数组
A.声明
(1)int
int[][] test_int;
(2)String
String[][] test_String;
(3)自定义类
MyClass[][] test_mc;
(4)对象数组
Integer[][] test_Integer;
B.初始化
数组名 = new 类型说明符[数组长度][];
数组名 = new 类型说明符[数组长度][数组长度];
对于没有初始化的维度,其值为null:
int arr[][];
arr = new int[3][4];
其相当于下述4条语句:
arr = new int[3][]; // 创建一个有3个元素的数组,且每个元素也是一个数组
arr[0] = new int[4]; // 创建arr[0]元素的数组,它有4个元素
arr[1] = new int[4]; // 创建arr[1]元素的数组,它有4个元素
arr[2] = new int[4]; // 创建arr[2]元素的数组,它有4个元素
其等价于:
arr = new int[3]\[];
for(int i=0;i<3;++i) arr[i] = new int[4];
对于二维数组,当只定义一维数组时,另一维的维数可以不一样,也就是说不一定是规则的矩阵形式。如:
int[][] arr;
arr = new int[3][];
arr[0] = new int[3];
arr[1] = new int[2];
arr[2] = new int[1];
C.使用foreach语句遍历二维数组
for(int[] arr1: arr){
for(int x: arr1){
System.out.print(x + " ");
}
System.out.println();
}
5.创建对象初始化顺序
(1)系统会对数据成员进行默认初始化
(2)执行数据成员定义处的初始化语句
(3)调用构造方法为数据成员指定初值
class IntClass {
int value; // 自动初始化,默认值为0
// int value = 5; // 在定义时指定初始化语句
public IntClass() {}
// 定义构造方法将属性value初始化
public IntClass(int val) {
value = val;
}
}
public class IntClassConstructor {
public static IntClass getInstance() {
// 调用构造方法,从而省略了s,value代码
IntClass s = new IntClass(8);
// s.value = 8;
return s;
}
public static void main(String args[]) {
IntClass a = new IntClass();
System.out.println(a.value);
a = getInstance();
System.out.println(a.value);
}
}
输出:
0
8
6.垃圾回收机制
7.数据成员又叫字段
8.final修饰常量
9.包package组织情况
1.对象三大特征:封装、继承、多态
一、封装
1.概念
封装就是利用抽象数据类型(类)将数据和基于数据的操作绑定在一起,数据被保存在抽象数据类型内部,系统只有通过被授权的操作方法才能访问数据。
封装性是面向对象编程的核心思想
特点:
(1)数据和基于数据的操作方阿飞构成一个统一体
(2)类的操作方法实现细节被隐藏起来,只是通过操作接口名称进行调用,操作内部的变动不会影响接口的使用
2.优点
只能通过规定方法访问数据
隐藏类实现细节
方便修改实现
方便加入控制语句
3.应用
修改属性的可见性:public, protected, private, “默认”(无任何修饰符)
创建公有的方法用于属性的读写
在属性读写方法中加入控制语句,判断属性值的合法性
public class People{
public String name; // 公有
protected int age; // 受保护
char sex; // 默认
private int money; // 私有
public int getMoney() { // 公有方法用于属性的读
if(money<0) return 0; // 判断属性值的合法性
return money;
}
public void setMoney(int money) { // 公有方法用于属性的写
if(money<0) this.money = 0; // 判断属性值的合法性
this.money = money;
}
}
4.This关键字
this调用类属性,即类的域变量 / 类字段 / 类数据成员
this调用本类中的其他方法
this调用本类中的其他构造方法,调用时要放在构造方法的首行
public class test {
public int money; // 成员属性 / 类字段
public test(){ // 构造方法1
this(233); // this关键字调用类中的其他构造函数
}
public test(int a){ // 构造方法2
this.fun(); // this关键字调用类中的其他方法
System.out.println(a);
}
public void fun(){
this.money = 666; // 使用this关键字给成员属性赋值
System.out.println(this.money); // 使用this关键字调用类字段
}
public static void main(String[] args) {
test myMoney = new test();
}
}
二、继承
1.概念
继承是Java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或类从父类继承方法,使得子类具有父类相同的行为。
2.特点
继承鼓励类的重用
继承可以多层继承
一个类只能继承一个父类(单继承)
父类中private修饰的不能被继承
构造方法不能被继承
继承的关键字extends
3.应用
(1)父类
public class Father {
/*成员属性*/
public String name; // 公有
public int age; // 公有
public char sex; // 公有
/*构造方法*/
public Father(){
System.out.println("Father无参构造方法");
}
public Father(String name){
this.name = name;
System.out.println("Father有参构造方法, Father的名字是:"+this.name);
}
/*成员方法*/
public void say() { // 公有
System.out.println("Father会说话");
}
public void eat(){ // 公有
System.out.println("Father会吃饭");
}
}
(2)子类访问父类成员属性
访问父类属性:super.name;(可以在其他方法和构造方法中使用)
public class Son extends Father {
public Son(String name){
super.name = name; // 给父类成员属性赋值
System.out.println(super.name); // 访问父类成员属性
}
public void fun(){
System.out.println(super.name);
}
public static void main(String[] args) {
Son son = new Son("xx");
son.fun(); // 调用子类fun函数
}
}
(3)子类访问父类构造方法
访问父类构造方法:
父类无参的构造方法:super();
父类有参的构造方法:super(name);
注意:访问父类的构造函数只能在子类的构造函数中访问,且必须是子类构造函数的第一行
public class Son extends Father {
public Son(){
super("**");
}
public static void main(String[] args) {
Son son = new Son();
}
}
(4)子类访问父类方法
访问父类方法:super.方法名();
public class Son extends Father {
public Son(String name){
super.eat(); // 访问父类的eat方法
}
public void fun(){
super.say(); // 访问父类的say方法
}
public static void main(String[] args) {
Son son = new Son("xx");
son.fun(); // 调用子类fun函数
}
}
总结super关键字:
super 只能出现在子类的方法和构造方法中
super 调用构造方法时,只能是第一句
super 不能访问父类的 private 成员
4.继承的限制
不能被继承的父类成员:
private成员
子类与父类不在同包,使用默认访问权限的成员
构造方法
5.多重继承初始化顺序
父类字段/属性
父类构造方法
子类字段/属性
子类构造方法
6.方法的重写
在子类中可以根据需要对父类中继承来的方法进行重写
重写的方法和被重写的方法必须具有相同方法名称、参数列表和返回类型
重写方法不能使用被重写的方法
public class Son extends Father {
public void say(){ // 子类方法重写
System.out.println("Son会说英语");
super.say();
}
public static void main(String[] args) {
Son son = new Son();
son.say();
}
}
三、多态
1.概念
多态是指一个程序中同名的不同方法共存的情况。
Java中提供两种多态的机制:重载(Overloading)与覆盖(Overriding)
2.实现思路
(1)编写父类
(2)编写子类,子类重写父类方法
(3)运行时,使用父类的类型,子类的对象
3.实现多态的三个必要条件
继承
重写
父类引用指向子类对象
public class Son extends Father {
public void say(){ // 子类方法重写
System.out.println("Son会说英语");
}
public static void main(String[] args) {
Father father = new Father();
father.say();
System.out.println();
Father fatherson = new Son();
fatherson.say();
System.out.println();
Son son = new Son();
son.say();
}
}
4.重载
方法名相同,参数类型或个数不同。
注意:若方法名相同,参数相同,返回类型不同,则编译不通过。
class Parent {
public int getScore() {
return 3;
}
public int getScore() {
return i;
}
}
5.覆盖
子类对父类的同名方法(方法名相同,参数相同,返回类型相同)重新进行定义,即在子类中定义与父类中已定义的同名而内容不同的方法。
class Parent {
public int getScore() { return 3; }
public String getCountryName() { return "China"; }
}
class Son extends Parent {
public int getScore() {
return 4;
}
public void function() {
System.out.println(super.getScore());
}
public static void main(String[] args){
Son s = new Son();
System.out.println(s.getScore());
System.out.println(s.getCountryName());
s.function();
}
}
6.重载和覆盖的区别
函数名 | 参数 | 返回值 | static | 多态 |
---|---|---|---|---|
同 | 不同 | 同/不同 | 重载 | |
同 | 同 | 同 | 重载 | |
同 | 同 | 同 | 不同 | 不同函数 |
同 | 同 | 不同 | 编译不通过 |
2.最小编程单元:类。
3.类的组合:一个类中放了本类/另一类的对象引用作为数据成员
4.高内聚、低耦合
5.子类继承父类的真正含义并不是将父类的属性和方法复制到子类当中,而是在生成子类对象的时候,将父类和子类的非静态的属性复制到子类对象当中(方法不复制)
6.Object类似所有类的共同祖先,即使定义类时美有写extends Object
7.被final修饰的类称为最终类,它不能有子类
8.被final修饰的方法不能在子类中覆盖
9.子类方法覆盖父类方法,子类的访问修饰符权限应等于或大于父类
10.同名的static方法和非static方法不能互相覆盖
11.抽象类中如果存在抽象方法,则具体子类必须对抽象方法进行覆盖
1.this三种用法:
(1)this.域变量、this.成员方法
(2)this(参数)——引用重载的构造方法
(3)this指代当前对象
2.super两种用法:
(1)super.域变量、super.成员方法(参数)
(2)super(参数)——构造方法的继承调用
若子类的域变量名或成员方法名与父类的域变量名或成员方法名相同时,要调用父类的同名方法或使用父类的同名域变量,则可用关键字super来指代。
3.初始化顺序:
(1)在调用任何一个构造方法之前,先进行类字段初始化
(2)在调用子类构造方法之前,先调用父类构造方法
4.抽象类、抽象方法(abstract)【等价于C++中纯虚函数】
5.接口 interface 是功能方法说明的集合,其中定义的数据成员全是 final static(静态常量)(即使没有任何修饰,其效果完全等效
6.接口没有构造方法,所有成员方法都是抽象方法。注意,方法前不能修饰为final
7.抽象类与接口比较:
(1)共同点:二者都有抽象方法,都不能实例化。都有自己的声明,并能引用具体子类或实现类对象。
(2)不同点
抽象类 | 接口 | |
---|---|---|
属性 | 可以有域变量 | 不能有域变量,只能是静态常量 |
成员方法 | 可以有具体方法,而且具体方法可以调用抽象方法 | 如果有方法,则全部是抽象方法 |
实现策略 | 必须有子类继承 | 必须有实现类实现 |
拓展性 | 弱 | 强 |
8.抽象类声明可以引用所有具体子类对象
9.父类声明可引用所有具体子类对象
10.子类声明不能引用平行级别的其他类对象,也不能引用父类对象
11.父类声明所引用的子类对象可以经过显式的转化(造型cast)赋值给子类声明,但子类声明所引用的子类对象赋值给父类声明则不需要显式的转化
12.对象用.equals()比较的是引用,用==比较的是引用
13.String用equals()比较的是值,用==比较的是引用地址
14.数值用==比较的是值
15.使用instanceof比较引用类型:
运算符的格式:a instanceof A,其中a为对象的引用,A为类。
如果a为A的实例或A子类的实例,则返回true;
如果a为A父类的实例,则返回false;
如果a对象的类和A没有任何关系,则编译不会通过。
16.内部类、匿名内部类
17.外部类无法直接访问内部类中的成员
1.异常声明
2.异常捕获
3.自定义异常 throw new 异常类
1.String的equals是值比较,严格区别大小写,可用equalsIgnoreCase忽略大小写比较
2.String的特点是一旦赋值,便不能改其指向的字符对象。如果更改,则会指向一个新的字符对象
3.编译器自动优化:
String s = "Hello";
String t = "Hello"; // s和t指向同一个字符对象
String s = "Hello";
String t = new String("Hello"); // s和t指向内存中不同的字符对象
4.StringBuffer是一个具有对象引用传递特点的字符串对象(拼接字符串等操作后不会创建一个新的String对象,而是对自身进行改变)
5.
6.String内部实现基于常量字符数组,内容不可变
7.StringBuffer(线程安全)、StringBuilder(非线程安全)基于普通字符数组,数组大小可扩容,内容可变
8.性能:StringBuilder > StringBuffer > String
1.两种创建线程的方式
(1)继承Thread类,覆盖其run方法;
(2)实现Runnable接口,将实现类对象作为参数传递给Thread类的构造方法。
2.多线程访问共享资源 --> 安全性问题 --> 同步机制(synchronized原子性)–> 上锁、死锁
1.两大集合框架:Collection、Map
4.Map的实现类:Hashtable、HashMap、TreeMap
5.Map遍历:
Set keys = map.keySet();
if(keys!=null){
Iterator iterator = keys.iterator();
while(iterator.hasNext()){
Object key = iterator.next();
Object value = map.get(key);
...;
}
}
Set entries = map.entrySet();
if(entries!=null){
Iterator iterator = entries.iterator();
while(iterator.hasNext()){
Map.Entry entry = iterator.next();
Object key = entry.getKey();
Object value = entry.getValue();
...;
}
}
1.标准输入:对象是键盘,Java对应类是System.in
标准输出:对象是屏幕,Java对应类是System.out
标准错误输出:对象也是屏幕,Java对应类是System.err
2.字节流
(1)InputStream
int read(byte b[ ]):读多个字节到数组中,返回读到的字节数目,如果读完则返回-1
int read(byte b[ ], int off, int len):从输入流中读取长度为len的数据,写入数组b中从索引off开始的位置,并返回读取的字节数,如果读完则返回-1
(2)OutputStream
write(byte b[ ]):将字节数组中的数据输出到流中
write(byte b[ ], int off, int len):将数组b从off指定的位置开始,长度为len的数据输出到流中
flush():刷空输出流,并将缓冲区中的数据强制送出
3.ByteArrayInputStream构造方法:public ByteArrayInputStream(byte[] buf)——将字节数组作为字节流的数据源
public class ByteArrayStream {
public static void main(String[] args) {
byte[] b = "hello".getBytes(); // String->byte[]
ByteArrayInputStream bais = new ByteArrayInputStream(b);
int n = 0;
while((n=bais.read())!=-1) {
System.out.print((char)n); // hello
}
}
}
4.ByteArrayOutputStream构造方法:public ByteArrayOutputStream()——构造一个字节数组输出流,用于将多少字节写入到流中,最后可以整体转换为一个字节数组
public class ByteArrayStream {
public static void main(String[] args) {
byte[] b = "hello".getBytes(); // String->byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(b,0,b.length); // 把b中length长度的字节数组写到输出流上
System.out.println(new String(baos.toByteArray()));
}
}
5.FileInputStream构造方法:FileInputStream(String name)——以文件路径名字构造一个文件输入流,打开一个与实际文件的连接,用于从该流中读取文件字节流
6.FileOutputStream构造方法:FileOutputStream(String name)——以文件路径名字构造一个文件输出流,打开一个与实际文件的连接,用于文件的写字节流操作
7.PipedInputStream和PipedOutputStream:通常用于将一个程序的输出连接到另一个程序的输入。
输出流作为管道的发送端,输入流作为管道的接收端。
使用前需要调用connect方法将输出流和输入流连接起来。
通常一个线程执行管道输出流的写操作,另一个线程执行管道输入流的读操作。
public class PipedStream{
public static void main(String[] args) throws IOEception {
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
new Thread(new Input(in)).start();
new Thread(new Output(out)).start();
}
}
class Input implements Runnable {
private PipedInputStream in;
public Input(PipedInputStream in) {
this.in = in;
}
public void run() {
byte[] buf = new byte[1024];
int len;
try {
len = in.read(buf);
String s = new String(buf, 0, len);
System.out.println("in "+s);
in.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
class Output implements Runnable {
private PipedOutputStream out;
public Output(PipedOutputStream out) {
this.out = out;
}
public void run() {
try {
out.write("hello".getBytes());
} catch(IOException e) {
e.printStackTrace();
}
}
}
8.字节流 --> 字符流:InputStreamReader(InputStream in)
InputStreamReader ins = new InputStreamReader(System.in);
9.字符流 --> 字节流:OutputStreamWriter(OutputStream out)或PrintWriter(OutputStream out)
OutputStreamWriter outs = new OutputStreamWriter(new FileOutputStream("test.txt"));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out), true);
out.println("Hello"); // 输出字符串“Hello”
10.过滤流BufferedReader的使用:用于缓存字符流,可以一行一行的读(只要是Reader的之类都可以作为BufferedReader的参数)
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
String c1;
int i = 0;
int[] e = new int[10];
while(i<10) {
try {
c1 = keyin.readline();
e[i] = Integer.parseInt(c1);
i++;
} catch(NumberFormatException ee) {
System.out.println("请输入正确的数字!");
}
}
11.过滤流DataInputStream和DataOutputStream,可从字节流中写入、读取Java基本数据类型,不依赖于机器的具体数据类型,方便存储和恢复数据
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("test.txt")));
dos.writeInt(3); // 写入整型
dos.writeDouble(3.14); // 写入浮点型
dos.writeUTF("hello"); // 写入字符串
dos.close();
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
System.out.println(dis.readInt()); // 读取整型,输出3
System.out.println(dis.readDouble()); // 读取浮点型,输出3.14
System.out.println(dis.readUTF()); // 读取字符串,输出hello
dis.close();
12.对象的串行化(Serialization)又称序列化,是将内存中的动态对象表达成为可以传输的串形式,而与之相反的过程则成为反串行化或反序列化。
13.对象串行化实现了Serialization接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象。
14.对象串行化的目的是为了便于网络传输和介质存储。
15.对象串行化和反串行化的实质是要解决对象在内存和物理存储之间如何进行映射,或者对象如何从一台计算机的内存映射到另一台计算机的内存上的问题。
1.OSI七层协议
层 | 功能 |
---|---|
物理层 | 比特流传输 |
数据链路层 | 两个相邻结点间的点到点的帧传输 |
网络层 | 为分组交换网上的不同主机提供通信服务,包括路由、地址解析等 |
传输层 | 为两主机间的进程通信提供可靠服务 |
会话层 | 提供网络中两主机之间会话的建立、维持和终止等 |
表示层 | 提供网络传输的标准格式 |
应用层 | 直接为用户的应用进程提供服务 |
2.TCP/IP四层协议:应用层、运输层、网络层、网络接口层
3.网络应用定位:
(1)IP地址:标识计算机等网络设备的网络地址。由四个8位二进制数组成。
例如:192.127.32.123
(2)域名:网络地址的助记符。
如:www.baidu.com
(3)服务类型:应用层提供的网络服务。
例如:http
(4)端口号:网络服务的标识号。
例如:80
4.统一资源定位器URL(Uniform Resource Locator):protocol://resourceName
(1)协议名(protocol):指明获取资源所使用的传输协议,如http
(2)资源名(resourceName):指明资源的完整地址,包括域名、端口号、文件名或文件内部的一个引用
例如:http://news.hzau.edu.cn/2015/1114/43886.shtml
5.可以通过URL的方法openStream()读取指定的WWW资源
6.可以通过URL的方法openConnection()连接WWW网络资源
7.127.0.0.1是TCP/IP协议中默认的本机地址
8.网络通信两类传输协议:TCP和UDP
9.TCP是一种面向连接的保证可靠传输的协议,TCP三次握手确立连接
10.Socket通讯的一般过程:
(1)创建Socket
(2)打开连接到Socket的输入/输出流
(3)按照一定的协议对Socket进行读/写操作:先启动服务端,再启动客户端,客户端向服务端发送字符串,之后处于阻塞等待状态;服务器收到客户端发送的字符串后显示,并处于向客户端发送字符的状态。当任何一端输入字符串“bye”后,退出程序,通讯中断
(4)关闭Socket(先关闭流)
11.获取连接到套接字的输入流/输出流
// 由Socket对象得到输入流,并构造相应的BufferedReader对象
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 由Socket对象得到输出流,并构造PrintWriter对象
PrintWriter os = new PrintWriter(socket.getOutputStream());
// 由系统标准输入设备构造BufferedReader对象
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
12.数据报是一种完备的、独立的数据实体,该实体携带有能从源计算机经网络正确路由到目的计算机的信息。不同数据报之间的通信信息相互独立,一个数据报之前和之后发出的数据报没有逻辑联系
13.DatagramSocket:用于在程序之间建立传送数据报的通信连接
DatagramPacket:用来表示一个数据报
1.JDBC(Java DataBase Connectivity)是Java面向对象应用程序访问数据库的接口API规范,它的出现使Java应用程序对各种关系数据库的访问方法得到统一
2.JDBC的驱动类型:
(1)100%纯JDBC驱动
(2)JDBC调用客户端
(3)JDBC/ODBC桥
3.使用JDBC操作数据库通常包含以下步骤:
(1)载入JDBC driver
(2)得到数据库的Connection对象,在客户端与数据库之间建立连接
(3)根据连接对象得到Statement进行查询或数据更新
(4)如果执行查询则返回的记录集ResultSet进行遍历操作;如果执行更新则根据成功与否的返回结构进行数据库事务操作
(5)操作结束后,依次对ResultSet、Statement、Connection执行关闭操作
4.JDBC异常处理统一由SQLException来捕获处理
5.Java反射机制(运行时获取自身信息)
假设Student是一个类,stu是Student类的实例对象的一个引用
(1)Class c1 = Student.class();
(2)Class c2 = stu.getClass();
(3)Class c3 = Class.forName("hzau.info.Student");
(4)Student stu = c1.newInstance(); // 运行时创建实例对象
(5)Method m = c1.getDeclaredMethod("方法名",可变参数列表(参数类型.class)); // 运行时获取类方法
(6)m.invoke(对象, 参数列表); // 运行时调用对象方法