java基础总结(小白向)

java入门基础总结(小白向)

1.类和对象的理解

​ 理解类和对象对应学习Java尤其重要,可以说类和对象贯穿整个Java语言。我们先给出类和对象比较官方的介绍。

​ 类:具有相同属性和方法的一组对象的集合。

​ 对象:类的一个具体实例。

​ --属性:对象的静态描述

​ --方法:对象的动态描述(可以是主动也可以是被动的描述)

​ 看似有一点高深,其实翻译成比较容易理解的大白话,就是模板和个体。打个比方:你家里有3只猫,这3只加猫同属一类,这一类叫家猫(或者说大一点类别:猫)。家猫是不是有一些固有的属性,比如毛色,眼睛的颜色,体重等等。家猫又有以下动作(方法)抓老鼠,喵喵叫,被撸。这时候家猫这个模板就出来啦。

​ 而对象是从对象中拷贝出来的实例个体,比如:这三只家猫分别叫Tom,mimi,kiki,并且其拥有自己独特的毛色等等,这三只猫就是三个对象(实例)。

这里先给出一代码框架出来先

class Cat{
    //属性
    String name;
    String Coatcolor;
    int eyecolor;     //这里用int类型代指眼睛颜色类型,1.绿 2.蓝具体可根据实际情况
    float weight;
    
    //构造函数后面会具体说明
    Cat(String name,String Coatcolor,int eyecolor,float weight){
        //一些赋值操作
    }
    //-------------------------------------------------------------------
    //方法
    public void catch(){
        System.out.println(name+"抓到老鼠");
    }
    //其余方法·······
}

2.类的创建

​ 这里介绍类的创建,也就是创建一个模板。如上述的代码一样,创建了一个模板。

​ 类的创建用关键字class来修饰,class这个关键字是告诉计算机你要创建一个类。class后面跟类的名字,就如上面的class Cat我创建了一个类,名字叫Cat(建议:类的名字首字母为大写)。具体创建格式如下。

	[访问权限修饰符]class 类名 [extends 父类] 
 {
  	//属性;
	//方法;   
 }
//[]为可选项,后面具体介绍,这里并没有写全
//可以根据上面代码进行对比

​ 类的方法是以函数的形式进行表达的,方法结构如下:

扫描二维码关注公众号,回复: 11513445 查看本文章
[访问权限修饰符] [final] [static] [abstract] void 方法名([形式参数列表]) [throws异常类]
{	
	//方法体
}
//[]可选项

包含主方法的类称为主类,主类是程序执行的入口点。主方法结构如下:

public class Dome{
	public static void main (String[] args){
		//主方法体
	}
}

属性,方法体外的变量或常量。

class Cat{
	//定义属性成员
	[访问权限修饰符][static]类型 变量名
	······
}

3.常量和变量

常量:数据在程序运行过程中值不发生改变,常量用final声明。

变量:一个命名的内存块,用于存储Java程序中的信息。

java的数据类型如下:

数据类型分:基本数据类型,引用数据类型

基本数据类型分:数值型:(byte,short,int,long,float,double),字符型(char),布尔型(boolean)

引用数据类型分:类(class),数组和字符串(String,char[]),接口(interface)

4.java选择结构

其实java的很多语法地方和C很相似,会C那么Java的选择结构基本是没有问题了。

//二分支选择
if (条件表达式){
	//当条件表达式为真时,执行改处语句块
}else{
    //否则,执行改处语句块
}


//多分支选择
if(条件表达式一){
    //条件表达式一为真时,执行改处语句块,否则跳转到下一条件表达式的语块
}else if(条件表达式二){
    //条件表达式二为真时,执行改处语句块,否则向下跳转
}else if(条件表达式三){
    //同理
}else{
    //都不成立,执行改语句块
}


//开关语句(switch)
switch(表达式){
       	case 常量1:
            语句块;break;
        case 常量2:
            语句块;break;
        
        ·······
        default:
        	必定输出语块;
}
//default为可选

5.java的循环结构

java的循环结构跟C类似,具体如下:

//for循环
for(表达式1;表达式2;表达式3){
	/*
	表达式1:初始化部分
	表达式2:循环条件
	表达式3:迭代部分
	*/
}

//条件循环(while)
while(条件表达式){
	//当条件表达式为真时,执行循环语句块
}

//条件循环(do-while)
do{
	//与(while)相似,不过是先执行一次然后再判断是否继续执行
}while(条件表达式);

说到循环结构就必须说一下跳转语句,jave支持三种跳转语句:

/*
	必须注意break和continue的不同,break是跳出整个循环体,而continue只是结束当前循环,如果条件允许,循环还会继续进行。
*/
break     //结束循环,跳出循环体
continue	//结束当前循环
return		//函数出口,返回一个值,或者空

6.类和对象的构造和创建

创建对象必须用new操作符,

new操作符的作用:
—为对象分配内存空间;
—调用类的构造方法;
—为对象返回一个引用(地址)。

​ 回到前面的代码中,会发现一个比较特殊的方法(函数),这个特殊的方法就叫做构造方法,或者叫做构造函数。

​ 每个类里面都有一个构造函数,构造函数主要完成对象创建时的初始化操作。构造方法的名称与类名一致,没有返回类型。

//这里就创建了一个对象mycat
Cat mycat = new Cat("tom","blue",2,10);
/*第一步在内存中声明了一个存放对象地址的变量,该变量称为对象名,此时值为null;
第二步用new调用构造函数并在内存中开辟一块存储空间,并把地址交给变量,此时对象名指向内存空间*/


这里重新说明一下构造函数:

/*
	每个类都必须有一个构造函数,当创建一个类时,java会默认给类添加一个隐式无参的构造函数,当程序员没写构造函数时,java默认调用隐式构造函数。
*/

class Cat{
	//属性(成员变量)
	String name;
    String Coatcolor;
    int eyecolor;    
    float weight;
//------------------------------------------------
//此处存在隐式构造函数。此函数给成员变量赋值null,或者0.

//------------------------------------------------
	public void catch(){
        System.out.println(name+"抓到老鼠");
    }
}


class Cat{
	//属性(成员变量)
	String name;
    String Coatcolor;
    int eyecolor;    
    float weight;
//------------------------------------------------
//当用户编写了构造函数,隐式构造函数将消失,不在被调用
	public Cat(String name,String Coatcolor,int eyecolor,float weight){
        this.name=name;
        this.Coatcolor=Coatcolor;
        this.eyecolor=eyecolor;
        this.weight=weight;
    }

//------------------------------------------------
	public void catch(){
        System.out.println(name+"抓到老鼠");
    }
}

对象的销毁

​ Java提供了资源回收机制,可以自动销毁无用的对象,收回其所占内存空间。
如果编程者需要主动释放对象,要重载Object父类中的finalize方法来释放资源,该方法一般在垃圾收集器删除对象之前被自动调用。这种情况不经常使用。

7.静态成员与实例成员

​ 实例变量:对象拥有的变量,通过对象(实例)来访问。

​ 每个对象创建时都为实例成员分配对应的内存空间。实例变量是独立的,每个对象都有属于自己的实例变量,类的每个对象都有自己的实例属性存储空间。

​ 静态变量:所有类和对象共享,通过类访问。静态成员有静态属性和静态成员方法,静态属性被所有对象共享。

​ 用static修饰符声明静态属性。一个静态属性只标记一个存储位置,多个类对象共享这个存储空间,即一个对象修改了值,另外一个对象取出的是修改后的值。

​ 静态方法:用static声明,用 类名.方法名(实际参数列表)的形式访问。静态方法体中不能访问类的实例成员。就是说类方法(对象共同拥有的方法)是无法访问实例变量和调用实例方法(非静态方法),并且不能使用this关键字。

下面通过代码理解一下

public class ex1 {

	public static void main(String[] args) {
		System.out.println("静态成员能通过类名直接调用A.A1:"+A.A1);
		A.test();
		
		A test1 = new A(1);
		A test2 = new A(2);
		
		System.out.println("--------------------");
		test1.test();
		test1.test2();
		
		System.out.println("--------------------");
		test2.test();
		test2.test2();
		
		System.out.println("--------------------");
		test1.change(5);
		System.out.println("test1和test2对象的静态变量更改成:"+test2.A1);
	}

}




public class A {
	static int A1=10;
	int A2;
	public A(int A2) {
		this.A2=A2;
	}
	
	public static void test() {
		System.out.println("静态方法只能访问静态变量A1:"+A1);		
	}
	
	public void test2() {
		System.out.println("非静态方法能访问静态变量A1:"+A1+"\t和非静态变量A2:"+this.A2);	
	}
	
	public void change(int x) {
		A1=x;
	}
}

输出结果如下:

静态成员能通过类名直接调用A.A1:10
静态方法只能访问静态变量A1:10
--------------------
静态方法只能访问静态变量A1:10
非静态方法能访问静态变量A1:10	和非静态变量A2:1
--------------------
静态方法只能访问静态变量A1:10
非静态方法能访问静态变量A1:10	和非静态变量A2:2
--------------------
test1和test2对象的静态变量更改成:5

关键字this的使用

在类的实例方法或构造方法中有一个名为this的引用,指向当前对象本身。

this可以引用属性(成员变量) -----this.属性
this也可以调用类中的其他成员方法 -----this.成员方法名(参数表)

this也可以调用本类的其他构造方法,不过必须位于构造方法中第一行。 -----this(参数)

this也可以作为return的返回值,返回对象本身。 -----return this;

8.方法的重载

​ 成员方法的重载,一个类中可以拥有多个方法名相同,签名不同的方法,称为该方法被重载。方法的签名:方法名、参数个数、参数类型。

​ 打个比方:输出函数中System.out对象中的println方法就有多个原型,实现了重载,可以实现对多种类型数据的输出。也就是说,两个名字相同的方法,只要其形参列表不同,那么者两方法就能同时存在,具体调用时,看传入参数来决定使用哪个方法。通过以下代码帮助理解。

public class A {
	public void run(int x) {
		System.out.println("这是重构方法1");
	}
	public void run() {
		System.out.println("这是重构方法2");
	}
}


//demo
public class test_main {

	public static void main(String[] args) {
		A a=new A();
		
		a.run(0);
		a.run();
	}
	
}

实验结果如下:

这是重构方法1
这是重构方法2

9.类的封装和访问控制

​ 封装性为软件提供了一种模块化的设计机制。设计者提供类模块,使用者用类模块组装更复杂的软件系统。java是面向对象语言,模块化的程序便于维护。而且java提供了访问权限的控制,java根据封装性要求,需要为类中的成员变量和成员方法提供不同的访问权限。

访问权限关键字,有public,protected,default(默认),private,访问权限由大到小。

public —本类 —本包和其他包 —子类 —非子类

protected —本类 —本包 —子类

default —本类 —本包

private —本类

​ public的权限范围是最大的,是公开属性,任何类都能调用public的方法,protected其次,除了其他包的非子类无法访问以外,其余都能访问。平时使用最多的是默认类,default可以不写,不写就是default。权限最小的是private,除了本类能访问外,其余都无法访问,若要访问,那么就必须一些Get,Set的公共类方法。

类级别:public 默认

成员级别:public protected 默认 private

老样子附代码帮助理解:

在这里插入图片描述

/*A.java*/
package test6;
public class A {
	public String a;
	protected String b;
	String c;
	private String d;
	public A() {
		System.out.println("创建public类A");
		a="public";
		b="protected";
		c="default";
		d="private";
	}
	public String getD() {
		return d;
	}
	public void setD(String d) {
		this.d = d;
	}
	
}

/*B.java*/
package test6;
class B {
	public String a;
	protected String b;
	String c;
	private String d;
	public B(){
		System.out.println("创建默认类B");
		a="public";
		b="protected";
		c="default";
		d="private";
	}
	public String getD() {
		return d;
	}
	public void setD(String d) {
		this.d = d;
	}
}

//C.java
package test7;
public class C {
	public String a;
	protected String b;
	String c;
	private String d;
	public C(){
		System.out.println("创建public类C");
		a="public";
		b="protected";
		c="default";
		d="private";
	}
	public String getD() {
		return d;
	}
	public void setD(String d) {
		this.d = d;
	}
}

//D.java
package test7;
import test6.A;
public class D extends A{
	public String a;
	protected String b;
	String c;
	private String d;
	public D(){
		System.out.println("创建public类D");
		a="public";
		b="protected";
		c="default";
		d="private";
	}
	public String getsuperA() {
		return super.a;
	}
	public String getsuperB() {
		return super.b;
	}
	public String getD() {
		return d;
	}
	public void setD(String d) {
		this.d = d;
	}
}

//test_demo.java
package test6;
import test7.*;
public class test_demo{
	public static void main(String[] args) {
		A demo1=new A();
		System.out.println("本包下能直接访问变量:"+"\ndemo1.a="+demo1.a+"\tdemo1.b="+demo1.b+"\tdemo1.c="+demo1.c);
		System.out.println("若要访问私有变量必须通过Get和Set方法,"+"demo1.getD="+demo1.getD());
		
		System.out.println("----------------------------------------------------------");
		B demo2=new B();
		System.out.println("本包下能直接访问变量:"+"\ndemo2.a="+demo2.a+"\tdemo2.b="+demo2.b+"\tdemo2.c="+demo2.c);
		System.out.println("若要访问私有变量必须通过Get和Set方法,"+"demo2.getD="+demo2.getD());
		
		System.out.println("----------------------------------------------------------");
		C demo3=new C();
		System.out.println("其他包下能直接访问变量:"+"\ndemo3.a="+demo3.a);
		System.out.println("若要访问私有变量必须通过Get和Set方法,"+"demo3.getD="+demo3.getD());
		
		System.out.println("----------------------------------------------------------");
		D demo4=new D();
		System.out.println("其他包下能直接访问变量:"+"\ndemo4.a="+demo4.a);
		System.out.println("若要访问私有变量必须通过Get和Set方法,"+"demo4.getD="+demo4.getD());
		System.out.println("D能访问父类C的变量:"+"\nsuper.a="+demo4.getsuperA()+"\tsuper.b="+demo4.getsuperB());
	}
}

输出结果:

创建public类A
本包下能直接访问变量:
demo1.a=public	demo1.b=protected	demo1.c=default
若要访问私有变量必须通过Get和Set方法,demo1.getD=private
----------------------------------------------------------
创建默认类B
本包下能直接访问变量:
demo2.a=public	demo2.b=protected	demo2.c=default
若要访问私有变量必须通过Get和Set方法,demo2.getD=private
----------------------------------------------------------
创建public类C
其他包下能直接访问变量:
demo3.a=public
若要访问私有变量必须通过Get和Set方法,demo3.getD=private
----------------------------------------------------------
创建public类A
创建public类D
其他包下能直接访问变量:
demo4.a=public
若要访问私有变量必须通过Get和Set方法,demo4.getD=private
D能访问父类C的变量:
super.a=public	super.b=protected

​ 请继续考虑test_demo与A,B,C,D的关系,和A和D类的关系。

​ 因为test_demo和A,B同一包下所以能直接创建A,B类的实例,并且能直接访问到A,B类的非私有成员属性,而C,D类不是同意包下,所以必须是public类的情况下才能直接创建,并且只能直接访问其public成员属性。而A和D是父子关系但不是同一包下,所以D能访问A的public和protected的成员。这里并没有考虑全部权限的使用情况,若考虑上构造器的权限,权限的使用情况会更加得复杂。这里就不一一列出了。

10.类的继承

​ 继承性是面向对象的核心特征之一,是从已有的类创建新类的一种机制。先创建具有共性的一般类,再从一般类派生出具有特殊性的新类,新类继承一般类的属性和方法,并定义了自己的新的属性和方法,我们就把这种机制称为继承。Java通过继承机制很好地实现了类的可重用性和扩展性。所以继承是java的一个重要知识点。在第9部分我们就使用了一点点类的继承。这里就给出猫类的继承树状图。

在这里插入图片描述

​ 这里猫就是野猫和家猫的父类,而野猫和家猫是猫的子类,子类也可以派生出新的子类,而且Java只支持单继承,也就是说一个父类可以有多个子类,但一个子类只能有一个父类。并且:

​ 祖先类:位于类层次树中较高层次的类。父类也称为直接祖先类。

​ 根类:Java提供了一个最顶层的根类Object(java.lang.Object),它是所有Java类的祖先类。

​ 这也就是说这里猫类其实是继承了java.lang.Object类,这个类一般不用写入代码中,因为java会隐式地添加上去,所以程序员不用可以刻意写上去。

​ 现在再说一下继承的优点,继承的优点包括:

1.提供了软件的可维护性。

2.增强了软件可扩充性。

3.提高程序代码的重用性和降低软件的复杂性并缩短软件的开发周期。

​ 因为继承增加了程序的模块化性,程序的模块化能提升软件的可维护性,并且因为继承可以在原有的父类代码下,添加一些新的元素从而派生出新的子类,可以很大地提高代码的重用性,我们就可以不必在编写某个模块时又要重头编写,只有在原有的父类下,添加新的元素,覆盖原有父类的属性和方法,或者添加一些private类的属性和方法,这样也可以创造出于父类有不完全相同的子类。

子类的定义和使用格式如下,

[权限修饰符] [其他修饰符]class 子类名 extends 父类名
	{
	  零到多个属性;
    零到多个构造方法;
    零到多个成员方法;
	}

[其他修饰符]包括一些abstract等
具体可以查看(9.类的封装和访问控制)中的代码A类和D类

​ 查看(9.类的封装和访问控制)中的代码A,D类和输出结果,如果你是细心的人的话,你会发现在创建D类的对象test4时是不是多一个(创建public类A)这个输出结果,其实这是在执行子类对象的构造函数里的语句前,会优先调用父类的构造函数,所以我们才会看到(创建public类A)这个输出结果。所以,子类对象的初始化调用子类构造方法时,要先执行父类的构造函数。子类构造方法中可以使用super显式调用父类构造方法,如果没有显式调用,则默认调用父类无参数构造方法。

通俗点说就是,要创建某个对象时,就必须在创建对象的爸爸的基础上创建对象。

10.2子类的使用和覆盖父类成员

Java中子类可以继承父类除构造方法的所有成员,但访问父类成员的权限如下:
(1)子类对父类的private成员(包括属性与方法)没有访问权限。如果需要访问父类的成员,可以通过父类中的非private成员方法来引用父类的成员。
(2)子类对父类的public或protected成员具有访问权限。
(3)子类对父类的缺省权限成员的访问分为两种情况:
对同一包中父类的缺省权限成员具有访问权限
对其他包中父类的缺省权限成员没有访问权限。

变量的覆盖

​ 再重新观察(9.类的封装和访问控制)中A,D类的代码,其中A有成员变量a,b,c,d,D也有成员变量a,b,c,d。这里D的成员变量隐藏了A中的成员变量,所以我们调用D类对象时我们是访问D类的a,b,c,d变量的。当我们创建D的对象时,我们会先调用A中的构造函数,而再运行D的构造函数,这就把原来A类中的成员变量隐藏了,所以我们调用D类的对象时是访问D的对象,而隐藏起来的父类成员可以在其子类中用super.变量名或者super.方法名来调用。

方法的覆盖

​ 方法的覆盖其实和变量的覆盖同理。含义:父类中的非私有成员方法被子类继承,但如果继承成员方法不能满足子类功能,则子类重写该方法。
要求:
(1)两个方法要具有完全相同的返回类型、方法名、形参列表。
(2)方法体要根据子类的需要重写,从而满足子类功能的要求。
(3)若子类中需要调用被覆盖的父类中的同名方法,通过super关键字来实现调用,即:super.方法名()

super的使用

super代指父类

访问父类被隐藏的成员变量: super.variable
调用父类中被override的方法:super.method ([paramlist])
调用父类的构造方法:super ([paramlist])

当然这不能super.super.·····这样子的连用

final关键字的使用

作用:

final成员变量:常量数据成员,不允许被修改。

final方法:阻止一个子类覆盖自己类中的方法,该方法不能被覆盖(重写)。

final类:该类不能派生出任何子类。

就是说被final标明的变量,方法,类都不能被修改,覆盖或者派生。并且,抽象类和方法不能声明为final,因为它一定会在子类的某个地方被再定义。

11.多态

​ 多态:是指一个程序中同名的不同方法共存的情况。指“一种定义,多种实现”。是面向对象的核心特征之一。其实上面说的方法重载,方法重写(方法的覆盖)和转型,构成了java的多态性。

​ 转型又分向上转型和向下转型,一个声明为父类的对象名,通过引用子类的实例来调用子类的方法称为**向上转型。即子类对象转型成父类类型,一个声明为父类类型的对象名,其值是子类对象的地址,可以调用子类中从父类继承下来的方法和覆盖的实例方法,但使用父类对象名引用子类对象,不能调用子类对象独有的实例方法。父类类型声明的对象转型成子类类型是向下转型**。即用父类类型声明的子类对象使用强制类型转换转换成子类类型,可以赋值给子类类型对象名。但是使用父类类型声明的父类对象向下转型成子类对象会出现运行时错误,不建议使用。

注意:子类覆盖(override)父类方法时,形参类型必须与父类保持一致,返回类型与父类的保持一致或是父类的方法的返回类型的子类型,此时该子类型称为协变返回类型。

12.抽象类

​ 抽象类是对抽象概念的描述,不能进行实例化。抽象类提供了方法声明与方法实现分离的机制,使各子类表现出共同的行为模式。抽象类中包含抽象方法,抽象方法在不同的子类中表现出多态性。

**1.**抽象方法(abstract method):

含义:没有方法体的方法,称为抽象方法。
抽象方法的声明格式:[权限修饰符] abstract 方法返回值类型 方法名(参数列表);

​ 一个abstract方法不能声明为private,因为private方法不能被继承,因此不能在子类中进行重新定义。构造方法不能声明为抽象的。

**2.**抽象类:

含义:用abstract声明的不能实例化的类。
声明格式:
[权限修饰符] abstract class 类名
{
类体
}

(1)在抽象类体中,可以包含抽象方法,也可以不包含抽象方法。但类体中包含抽象方法的类必需要声明为抽象类。举例:通过接口接入抽象方法,虽然类体里面没有抽象方法,但是此类为抽象类。

(2)抽象类不能实例化,即使抽象类中没有声明抽象方法,也不能实例化。抽象类代表有还没有方法体的方法,所以是无法实例化的。

(3)抽象类的子类只有给出每个抽象类方法的方法体,即覆盖父类的所有抽象方法后,才能创建子类,如果有一个抽象方法未在子类中被覆盖,该子类也必须被声明为抽象类。就是说只有还有没有被实现的方法,就无法实例化。

13.内部类与外部类

内部类:嵌套在一个类内部的类

外部类:包含嵌套类定义代码的类

顶层类:类定义代码不嵌套在其他类定义中的类。顶层类不能被其他类包含。

​ 内部类可直接访问其外部类的所有成员。外部类不能直接访问内部类的成员,必须要创建内部类的实例,然后使用对象名作前缀来访问内部类的所有成员。

​ 前面我们学过了成员的覆盖(重写)值得注意的是内部类是允许继承的,并且内部类可直接访问其外部类的所有成员。那么当内部类的父类成员和外部类的成员重名时,是优先访问那个类的成员呢。这里给段代码方便自己到时翻看以前的笔记时方便理解:

public class SuperCls{
	string s="super";
}

public class OuterCls {
  String s = "outer";

  class Inner extends SuperCls {
    //String s = "inner";
    void print(){
      System.out.println(s);
    }
  }
}

/*test函数代码*/
OuterCls out=new OuterCls();           
OuterCls.Inner inner=out.new Inner();     //创建内部类,必须依附在外部类对象上
inner.print();

//这里是输出
super

所以访问顺序是内部类,父类,外部类。父类优先级是比外部类高的。

内部类的创建有一点必须值得注意的是,内部类的创建必须依附在外部类的对象上,也就是说若要创建内部类,就必须创建外部类类先,或者在外部类内部直接创建。

创建方式:

//在外部类外创建非静态内部类
outer.inner in = new outer().new inner();

//在外部类外创建静态内部类
outer.inner in = new outer().inner();

//在外部类内创建非静态内部类
inner in = new inner();

//在外部类内使用静态内部类(无需创建)
inner.方法名();

内部类和外部类相互访问变量的方法,如下:

public class Demo {

	public static void main(String[] args) {
		Outer o = new Outer("外部类的变量");
		o.outMethod();
		
		Outer.Inner i = o.new Inner();
		
		System.out.print("其他类访问:");
		i.inMethod();
		
	}

}

public class Outer {
	private String outStr;

	Outer(String s) {
		outStr = s;
	}

	public void outMethod() { // 外部类中访问内部类成员的方法
		Inner in = new Inner(); // 创建内部类实例
		
		System.out.println("outMethod访问:" + in.inStr);
		in.inMethod();
	}

	class Inner {
		private String inStr = "内部类的变量";

		public void inMethod() {
			System.out.println("inMethod访问:" + outStr);
		}
	}

}

//输出结果
outMethod访问:内部类的变量
inMethod访问:外部类的变量
其他类访问:inMethod访问:外部类的变量

14.包

​ **1.**包是为了便于管理大型软件系统中数目众多的类,解决类命名冲突的问题。由.class文件组成的一个集合,在物理上包被转换成一个文件夹,组织形式是一种层次结构,包中还可以再有包。功能相同或者相关的类组织在一个包中。

​ 比较常见的包有:java.lang基础包(Java类中的默认引入的包,包含公共基类Object,常用类System,String等),java.util工具包(Scanner类等),java.sql数据库包,java.io输入输出流包(InputStreamReader,BufferedReader,IOException等),java.net网络包等。

Java的核心包,包名以“java”开始,Java的扩展包,包名以“javax”开始。

语法格式是:package 包名1.包名2.包名3······

在package语句中,用“.”来指明包(目录)的层次。

​ 关于包的管理,许多IDE(集成开发工具)都有包的管理,包的管理的细节大部分工作已经交由IDE处理。

​ **2.**包的引入

​ 包的引入是通过import语句进行引入的,语法格式为import 包名1.包名2.·····.类名,其实import语句是以类为单位进行引入的,就如:

引入整个包里面的所有类 import 包名.*

引用某个包中的某个类 import 包名.类名

​ 其实import语句某种意义下是属于将某个类路径更名,因为不使用导入语句,仍然使用某个类,例如:test.demo1.test_main A=new test.demo1.test();也可以通过这种写类的全名来进行类的创建。这里就不详细说了,这里给个链接,里面有import的作用详解。
https://blog.csdn.net/qq_25665807/article/details/74747868.
(这个真的很不错,说得十分详细)。

15.接口

1.接口的基础

​ 接口(interface)在Java中应用非常广泛,能很好地体现Java的面向对象编程思想。接口的目的在于对象的抽象处理,使设计和实现分离。

​ 接口的另一个重要作用是弥补Java只支持单继承的不足。一个类可以实现多个接口,这样就实现了多重继承的功能。

​ 接口是一组相关常量和(或)抽象方法,在大多数情况下,接口只包含方法。作用是指定一组方法来表示一个特定的类接口,而这些方法能在很多不同的类中正确地实现。所有类都可以共享这个通用的接口,且可使用接口类型的变量来多态调用其中的方法。

​ 这里给出几个知识点:

1.可在抽象类中定义方法的默认行为,但是接口的方法不能拥有默认行为。

2.如没有指定接口方法和属性的访问权限,Java将其隐式地声明成public。

3.extends表示的是一种单继承关系,而一个类却可以实现多个接口,表示的是一种多继承关系。

4.如要表示的两类事物在本质上是相同的,则使用继承;如果要表示的两类事物在本质上是不同的,但有相同名字的属性或方法,则使用接口。

5.接口中的属性成员,默认为常量。

6.接口中的方法在默认状态下总是public和abstract类型的。

7.接口中的常量在默认状态下总是public、static、final类型的。

2.接口的继承

接口的继承:使用extends在一个接口基础上定义另一个接口。

优点:扩展后的接口从其原始接口得到所有方法和常量。

多重继承:接口有一点是要注意的,那就是接口是允许多继承的,在Java语言中,类不支持多重继承,而接口支持。

3.接口的定义
public interface Ianimal{
   //方法都默认为abstract类,abstract方法没有方法体
   public void eat();
   public void sleep();
}
4.嵌套接口

接口能定义在其他类和接口的内部,并且接口可以使用权限声明有public,pricate,protected.

public class A { 
  public interface B { // 嵌套接口
       void method();
   }
}

接口的引用用implement来进行引用

public class C implements A.B {
   public void method() {
   System.out.println("实现嵌套接口method()方法");
   }
}

接口内部也可以定义类,一个接口的内部类在默认情况下是static和public类型。

例如:

interface Port {
   class  Info  {      
   	//类体
   }
}

​ 这里补个链接https://www.cnblogs.com/lesliefang/archive/2013/04/18/3029622.html链接里的文章有说Java内部静态类,虽然Java的内部静态类用得真的很少,不过作为知识点来补充也不错。

16.Java异常处理机制

1.异常处理的概述

​ 异常就是程序执行时出错的情况。对出错情况作出相应的处理叫做异常处理,通常异常处理有两个方面:

一.由计算机系统本身检验错误并给出错误信息和终止程序的执行;

二.由程序员在程序中添加异常处理功能。

​ Java语音异常处理时是可以将异常情况在方法调用中进行传递,直到将异常传递到可以处理的位置。java的异常是向上传递,也就是说当某段代码出现异常,在当前函数下没有进行异常处理,那么异常就会传递到调用此异常函数的上一层函数。

2.异常处理的语法

​ 异常处理用关键词try和catch,其中try为要执行的代码段,catch为要捕捉的异常并对异常执行处理的代码段。

try{
	//执行代码块
}catch(异常表达式一){
	//异常处理
}catch(异常表达式二){

}finally{

}

//finally为非必须语句块,finally无论try语句块有没有发生异常都会执行。一般用来收尾的。
3.异常的类型

1.Throwable:java.lang包中专门用来处理异常的类。

Java程序抛出的异常对象必须是Throwable类及其后代类对象。

Throwable类有两个直接子类:1.Error类 2.Exception类

2.Error类及其子类主要包括:虚拟机错误、装载错误、动态连接错误,因为这类异常主要是和硬件和环境有关系,并且不是由程序本身抛出。所以Java程序不对这类异常进行处理。

3.Exception类,又分成两大子类,第一大子类RuntimeException类及其子类,该类异常是程序运行时异常,也就是由程序自身的问题导致产生的异常,该类异常不要求程序必须处理。第二大子类,直接继承Exception类。该类异常属于程序外部的问题引起的异常,也就是由于程序运行时某些外部问题导致产生的异常,如文件不存在异常等。该类异常Java编译器要求Java程序必须处理。

由Exception类派生的非RuntimeException类,编译器将检查是否进行了处理:1.是否在try{}catch{}语句中捕获并处理了异常。2.是否声明方法时注明抛出该异常。若两项工作都未做,则无法编译。

4.抛出异常

​ Java允许主动抛出异常,使用关键词throws来声明抛出的异常类。为了说明方法可能抛出的异常,只需将关键字throws书写在方法的形参表之后,加上可能抛出异常类的清单,这些异常类用逗号隔开。
根据异常的向上传播效应,如果中间的调用方法没有处理异常,异常最后会到达main方法交给系统处理。

​ 如果需要在程序中自行抛出异常,则应使用 throw 语句,throw 语句可以单独使用,throw 语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例。

​ 如果想深入了解throw的用法,这里给个链接https://blog.csdn.net/weixin_43819113/article/details/91468459后面大部分细节的都以链接方式给出,主要是细讲的话篇幅会十分大。(主要是懒)

17.Java API

这里介绍一些Java比较经常使用的类包。这里给个JDK14开发文档https://docs.oracle.com/en/java/javase/14/docs/api/index.html

1.java.lang包

1)String类:提供了字符串连接、比较、字符定位、字符串打印等处理方法。

2)StringBuffer类:提供字符串进一步的处理方法,包括子串处理、字符添加插入、字符替换等。

3)Math类:提供大量的数学计算方法。

4)System类:提供对标准输入、输出设备的读写方法,包括键盘、屏幕的in/out控制。常用的System.out.print()、System.out.println()都是该类的静态属性输出流out所提供的方法。

5)Thread类:提供Java多线程处理方法,包括线程的悬挂、睡眠、终止和运行等。

6)Object类:这是Java类的祖先类,该类为所有Java类提供了调用Java垃圾回收对象方法以及基于对象线程安全的等待、唤醒方法等。

7)Throwable类:该类是Java错误、异常类的祖先类,为Java处理错误、异常提供了方法。

2.java.io包

提供数据流方式的系统输入输出控制、文件和对象的读写串行化处理

BufferedInputStream / BufferedOutputStream 字节型输入输出流
BufferedReader / BufferedWriter 字符型输入输出流
DataInputStream / DataOutputStream 字节型输入输出流
FileReader / FileWriter 字符型输入输出流
FileInputStream / FileOutputStream等。 字节型输入输出流

3.java.applet包

​ 此包只有一个Applet类,用于开发或嵌入到网页上的Applet小应用程序,使网页具有更强的交互能力以及多媒体、网络功能。Applet是用Java编程语言编写的小应用程序,该程序可以包含在 HTML页面中。

4.javax.swing包

​ 提供Java编写的图形界面创建类,支持各种操作平台的界面开发。swing包还提供了树形控件、标签页控件、表格控件的类。javax.swing包很多类都继承java.awt包的类。

5.java.net包

​ 提供网络开发的支持,包括封装了Socket套接字功能的服务器ServerSocket类、客户端Socket类以及访问互联网上的各种资源的URL类。

18.比较常用的类

String类

​ Java自带的标准final类,字符串了。有final字段说明是无法被继承的了。String放在java.lang包中,lang包默认自带引入。所以不需要用import语句引入。

​ 既然String是类那么先说一下String类的构造函数

String()                  //初始化一个新的String对象,使其包含一个空字符串
String(char[ ] value )     //分配一个新的String对象,使它代表字符数组参数包含的字符序列
String(char[ ] value, int offset, int count)
//分配一个新的String对象,使它包含来自字符数组参数中子数组的字符
String(String  value )      //初始化一个新的String对象,使其包含和参数字符串相同的字符序列
String(StringBuffer  buffer )    
//初始化一个新的String对象,它包含字符串缓冲区参数中的字符序列

创建String变量的方法:

利用构造方法创建:String s=new String(“new string”);

利用常量初始化:String s= “new string”;

两者有本质上的区别,要理解区别首先要对java的内存管理有一点认识。

java内存管理

​ Java程序用字符串池管理字符串,Java程序运行时JVM会在内存创建一个字符串缓冲池,字符串常量保存在字符串缓冲池中,相同的常量只允许保存一个。

​ 栈(stack)用来保存基本类型(或者叫内置类型,主要有char、byte、short、int、long、float、double、boolean)和对象的引用(地址),数据可以共享,速度仅次于寄存器(register),快于堆。

​ 堆(heap)是用于存储对象的内存空间,字符串缓冲池在堆空间内,堆中可以存放隐式对象(如字符串常量),也可以存放显式对象(如用new创建的对象)。

/*
	假设我现在创建3个字符串变量,其中s1和s2是利用常量初始化,而s3和s4是利用构造方法创建。
*/

String s1 = "new string";
String s2 = "new string";
String s3 = new String("new string");
String s4 = new String(s1);

//这里画了个图

在这里插入图片描述

所以如果你们使用==和equals方法对比字符

可以得出以下结果

/*
	==是引用对比
	equals在String中重写了,所以是进行值的对比
*/
s1 == s2
s1 != s3
s1 equals s3

/*顺便介绍一下字符串的intern()方法,调用该方法时,去查字符串缓冲池中是否有该字符串,若存在,则返回缓冲池中的字符串引用,若不存在,在缓冲池中添加该字符串,并返回引用。该方法确保字符串在字符串缓冲池中一定存在。*/

s3=s3.intern();

//结果
s1 == s3

​ String类变量是一个保存String类对象的引用(地址)的变量。当执行赋值语句时,原来的引用就被新字符串的引用所覆盖,原来的字符串被丢弃。不用程序员去释放原有对象的内存空间,因为Java有垃圾回收机制。会自动释放无用的内存空间。

​ String类字符串之所以不能被更改是因为,其实质上是通过一个private final char value[ ];的属性变量来实现字符串的存储的。因为被用final标记的变量是无法更改其值的,也就是说它是常量。所以在对String类字符串进行更改时都是新建一个字符串并返回引用来实现的。所以你会发现String类中对字符串进行修改的方法最终都会返回一个引用,因为那个引用就是新的字符串引用。

StringBuffer类

字符串可以分为两类:

一,永久字符串:不可被更改的字符串,即存放字符串的内存的内容不可用被更改,如String对象。

二,可变字符串:可以被更改的字符串,即内存的大小可以扩展,里面的内容可以被更改。如:StringBuffer对象,StringBuilder对象。

​ 其中StringBuffer对象:适用于多线程。StringBuilder对象:适用于单线程,操作要快于StringBuffer对象。

​ 又因为StringBuffer对象是不支持字符串缓冲池的引用,所以StringBuffer的引用是不能像String对象那样只使用字符串常量做初始值。

这里给个StringBuffer类构造函数的代码

public StringBuffer() {
        super(16);
    }
    
public StringBuffer(int capacity) {
        super(capacity);
    }
    
public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
    
/*其中他们用使用了父类的构造函数来实现构造,他们的父类是AbstractStringBuilder类,就算不看父类代码大概都能猜测出其构造函数的作用*/
System类与Runtime类

System类该类是与系统相关的属性和方法的集合,它的所有属性和方法都是静态的,用类名访问即可。

​ public static String getProperty(String key),该方法根据参数key值获得和系统相关的属性值,DK中已经定义好的key值在JavaAPI文档的System类的getProperties方法的文档中可以查看。

​ public static long currentTimeMillis(),该方法获取当前系统时间距离UTC(协调世界时) 的1970年1月1日0点0时0分0秒的毫秒数。

​ public static void gc(),该方法表示运行Java虚拟机的垃圾回收机制,尽最大可能回收垃圾,释放内存。但是否立刻释放,要看具体实现。

​ public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)该方法实现数组的复制,把源数组从特定位置开始,复制到目标数组的特定位置,可以设置复制的元素个数。该方法是一个native方法(java调用非java代码的接口),所以效率比for循环拷贝要高。所以数组的拷贝复制建议使用。

​ public static void gc(),该方法表示运行Java虚拟机的垃圾回收机制,尽最大可能回收垃圾,释放内存。但是否立刻释放,要看具体实现。

Runtime类该类封装了Java虚拟机运行时的环境。每个Java应用程序都有一个Runtime类实例,使该程序能够和其运行的环境相连接。应用程序可以通过Runtime类的静态方法getRuntime()获取Runtime的实例,从而获取虚拟机的信息。

​ public static Runtime getRuntime()获取Runtime实例

​ public int availableProcessors()获取虚拟机处理器数目

​ public long totalMemory()获取虚拟机内存大小

​ public long freeMemory()获取虚拟机空闲内容大小

​ public long maxMemory()获取虚拟机试图使用的最大内存量

​ public Process exec(String command)执行参数所表示的外部命令,返回一个进程对象,来管理执行的这个进程

Math类与Random类

Math类:存在于java.lang包,可用于求一些数学运算。

Random类:存在于java.util包中,生成各种类型的随机数。

所以Math类不需要引入。

Math类

Math类方法:

public static int ceil(double a) 返回大于或等于a的最小整数

public static int floor(double a) 返回小于或等于a的最大整数

public static int abs(int a) 返回a的绝对值

public static int max(int a,int b) 返回a和b的最大值

public static int min(int a,int b) 返回a和b的最小值

public static double random( ) 返回一个伪随机数,其值介于0和1之间

其余方法请查看API文档

Random类

Random包含在java.util包中。

Random有两个构造方法:

Random( )(使用系统时间为种子数)

Random(long seed)

Random类的nextInt( )方法能生成一个伪随机数;

Date类

表示特定的瞬间,精确到毫秒。

允许把日期解释为年、月、日、小时、分钟和秒值。它也允许格式化和解析日期字符串。

Date date = new Date();
System.out.println("当前日期为:" + date);
/*
	这里的date是调用了toString函数方法,直接打印函数的引用Java会默认调用toString()函数。
*/

采用DateFormat类的方法格式化或过滤所需要的数据参数

Date date = new Date();
String str =DateFormat.getInstance().format(date);
System.out.println("格式化日期:"+str);
/*
	这里DateFormat.getInstance()返回的是一个DateFormat对象,然后调用format方法
*/

采用SimpleDateFormat类的方法格式化或过滤所需要的数据参数

SimpleDateFormat time = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
System.out.println("日期时间为:"+ time.format(date));

这里给个代码

public static void main(String[] args) {
		Date date = new Date();
		System.out.println(date.toString());
		String strdate = DateFormat.getInstance().format(date);
		System.out.println(strdate);
		
		System.out.println(DateFormat.getDateInstance(DateFormat.FULL).format(date));
		
		
		DateFormat shortDateFormat = DateFormat.getDateTimeInstance(
				DateFormat.SHORT, DateFormat.SHORT);

		DateFormat mediumDateFormat = DateFormat.getDateTimeInstance(
				DateFormat.MEDIUM, DateFormat.MEDIUM);

		DateFormat longDateFormat = DateFormat.getDateTimeInstance(
				DateFormat.LONG, DateFormat.LONG);

		DateFormat fullDateFormat = DateFormat.getDateTimeInstance(
				DateFormat.FULL, DateFormat.FULL);

		System.out.println(shortDateFormat.format(date));
		System.out.println(mediumDateFormat.format(date));
		System.out.println(longDateFormat.format(date));
		System.out.println(fullDateFormat.format(date));

	}

输出结果

Fri Mar 27 17:04:51 CST 2020
2020/3/27 下午5:04
2020年3月27日星期五
2020/3/27 下午5:04
2020年3月27日 下午5:04:51
2020年3月27日 CST 下午5:04:51
2020年3月27日星期五 中国标准时间 下午5:04:51

19.Java基本类型包装器

​ Java的基本类型是重C继承而来的,并且Java提供了将基本数据类型进行了包装,形成类。一个包装器类的对象可以存储对应基本数据,还可以提供相关的方法和属性。

基本类型					 包装类
int							Integer
byte						Byte
short						Short
long						Long
float						Float
double						Double
char						Character
boolean						Boolean

Integer

//这里介绍变量,这是从API文档找到的
Modifier and Type				Field        Description
static int						BYTES		 以二进制补码形式表示整型值的字节数。
static int						MAX_VALUE	 一个常数,int能存储最大的值
static int						MIN_VALUE    一个常数,int能存储最小的值
static int						SIZE		 int占用位数
static class<Integer>			TYPE       	 数据类型

//方法就不介绍了,具体请看API文档

​ 你可以把基本类型包装器理解成,在原数值的基础上,添加一些属性描述,和数据转换的方法。其他的基本类型包装器就不在这里说了,其实他们都差不多。这里再介绍一下装包和拆包。

//装包
//构造函数有两个
Integer(int value)          Integer(String s)
Integer x = 5;  //自动进行装包;等价Integer x = new Integer(5);

//拆包(其实就是返回原有值)
int i = x.intValue();
int i = x;     //自动进行拆包

20.泛型

Java泛型实现了把类型作为参数。这怎么理解呢,给个代码吧

//值得注意的是基本类型不能用在泛型上
class PointDemo<T> {      //这里的泛型T可以当成一个参数,具体类型通过创建对象时给出
	    private T x;
	    private T y;
	    public void setX(T x){
		  this.x=x;	    
		  }
	    public void setY(T y){
		  this.y=y;	    
		  }
	    public T getX(){
		  return x;	    
		  }
	    public T getY(){
		  return y;	    
		  }
}

public class PointTest {
public static void main(String[] args){
   //(2)生成泛型类的对象(确定T的类型)   注意不能传基本类型,如int
	PointDemo<Integer> p1=new PointDemo<Integer>();      //把Integer赋值给T
	PointDemo<Float> p2=new PointDemo<Float>();
	PointDemo<String> p3=new PointDemo<String>();
	//设置整型类型的坐标值
	p1.setX(30);     
	p1.setY(50);
	//设置浮点类型的坐标值
	p2.setX(30.2f);  
	p2.setY(50.1f);
	//设置字符串类型的坐标值
	p3.setX("东经");  
	p3.setY("北纬");
	System.out.println("x1、y1的坐标值为:"+p1.getX()+p1.getY());
	System.out.println("x2、y2的坐标值为:"+p2.getX()+p2.getY());
	System.out.println("x3、y3的坐标值为:"+p3.getX()+p3.getY());	}
}

21.集合类

​ 在Java中集合类用来批量存放对象的,相当于一个容器,里面包含着一组对象,其中每个对象作为集合的一个元素出现。Java API提供的集合类位于java.util包内。

​ Collection中可放不同类型数据,是Set接口和List接口的父接口。能放不同类型数据,意味着,集合类里面能放多种类型数据。其中Collection是作为List和Set父接口。

​ 这里看一下Collection接口的方法。可以看到add函数中的形参是泛型,说明可以添加各种类型。

boolean add(E e);                //添加元素e到collection 中。 其中E为泛型。
void clear();                    //移除此 collection 中的所有元素(可选操作)。
int size();						//返回此 collection 中的元素数。
boolean remove(Object o);        //从此 collection 中移除指定元素的单个实例,如果存在的话									//(可选操作)。Object表示任何类型。
/*   其余方法请自行查找*/

​ 顺便说一下Collection的子接口。Set是无序的集合接口,元素存入顺序和集合内存储的顺序不同,不允许元素重复,其实现类有HashSet(无序),TreeSet(有序)等。List是有序的集合,允许元素重复,List中的元素都对应着一个整数型的序号,记载其在容器中的位置,可以根据序号存取容器中的元素,主要实现类有ArrayList类及LinkedList类。

1.ArrayList类

​ ArrayList类继承于java.util.AbstractList,使用Collection和List等接口。

ArrayList有以下几个特点:

​ 1.线性顺序存储

​ 2.可以存储重复数据

​ 3.ArrayList的大小可动态改变,可看成动态数组或Array的复杂版本

​ 提供如下构造方法:

public ArrayList();      //默认的构造方法,以默认的大小(16) 初始化内部的数组。
public ArrayList(Collection c);  
//用一个Collection对象来构造,并将该集合的元素添加到ArrayList。
public ArrayList(int n);    //用指定的大小来初始化内部的数组。

​ 常用方法:

public boolean add(E e);
public boolean add(int index,E e);
public Object remove(int index);
public T[] toArray(T[] a);
public E get(int index);
public int indexOf(Object o);
/*具体作用就不说了,请自行查找*/

2.LinkdeList类

ArrayList由数组实现,随机访问效率高,随机插入和删除效率低。

LinkedList由双向链表实现,随机访问效率低,随机插入和删除效率高。

LinkedList提供了以下构造方法:

public LinkedList();
public LinkedList(Collection c);

常用方法:

public boolean add(Object e);
public Object remove(int index);
public Object get(int index);
public void addFirst(E e);
public void addLast(E e);
public E remove(int index);
public E remove();
public E removeFirst();
public E removeLast();
/*具体作用就不说了,请自行查找*/
3.HashSet类

​ HashSet继承Set接口,不允许有重复元素。主要用哈希算法确定元素在集合中的位置。HashSet集合在用add()方法添加一个新对象时。实际是HashSet是使用一个HashMap对象存储数据的,把元素以Map的Key值存储。

22.迭代器

这里说一下迭代器:

Iterator:是Java迭代器最简单的实现,用于对 collection 进行迭代的迭代器。

ListIterator:为List设计,具有更多功能,可从两个方向遍历List,也可从List中插入和删除元素。

​ 迭代器是一种设计模式,作用是在于对数据的遍历与数据的内部表示进行分离。Collection对象可以调用iterator(),放回一个iterator对象。

这里介绍一下iterator常用方法:

next();
/*第一次调用next()方法时,它返回序列的第一个元素,以后再次调用时将获得序列中的下一个元素。*/
hasNext();
//Iterator对象调用该方法检查序列中是否还有元素。
remove();  //Iterator对象调用该方法删除上次调用next方法获取的元素。

Iterator和ListIterator区别:

1.ListIterator有add()方法,可向List中添加对象,而Iterator不能。

2.ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可实现逆向(顺序向前)遍历,而iterator不可以。

3.ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

4.ListIterator和Iterator都可实现删除对象,但是ListIterator可以实现对象的修改,可以利用set()方法实现对LinkedList等List数据结构的操作。Iterator仅能遍历,不能修改。

下面用代码对其进行简单的介绍

//假如我们有一collection
ArrayList<File> al = new ArrayList<File>();   //只能存File类的列表(这里使用了泛型确定的传入的元素是File类型)
Iterator iter =al.iterator();     //通过集合类的iterator()方法返回对应的迭代器
while(iter.hasNest())
	System.out.println(iter.next().toString());      //遍历列表中的元素
//使用迭代器的好处是我们不用考虑集合中元素的个数,而且效率也高。

//还有其他写法,一般for循环写法比如:
ArrayList<File> al = new ArrayList<File>();   //只能存File类的列表
Iterator iter =al.iterator();     //通过集合类的iterator()方法返回对应的迭代器
for(File f=iter.next();iter.hasNest();)
	System.out.println(f.toString());      //遍历列表中的元素

//常用版效果等同于上面for循环
ArrayList<File> al = new ArrayList<File>();   //只能存File类的列表
for(File f:al)
	System.out.println(f.toString());      //遍历列表中的元素


23.流

​ 流是输入和输出设备的一种抽象表示,这些设备是数据源或数据终点。可以把流想象为流入程序变量内存空间或从变量内存空间中流出的字节序列。引入流的好处:1.不必担心各种设备的具体工作机制,对于它们的管理均在幕后进行。2.用户的程序可以适用于各种输入输出设备,改变输入输出设备时不用改写程序编码。特点是:每个数据都必须等待排在它前面的数据读入或送出之后才能被读写;每次读写操作处理的都是序列中剩余的未读写数据中的第一个,而不能随意选择输入输出的位置。

FileInputStream fis = new FileInputStream(path);
//可以把fis看成字节序列(path为磁盘文件路径)

fis.read();
//从磁盘中读取1字节到内存中(从字节序列中读取1字节数据)或着说是从流中读出一个字节的数据
//输入输出流是相当于内存来讲了,读入到内存的叫输入流,从内存写到其他设备叫输出流。

输入流:从外设流入计算机内存的数据序列;文件,当从其中读取数据时,使用输入流和它关联。键盘是标准输入设备,和输入流关联。

输出流:从计算机内存流向外设的数据序列,即把数据写入流时,该流称为输出流。文件,当向其中写数据时,使用输出流和它关联;屏幕是标准输出设备,和输出流关联。

另外,根据流中数据单位的不同,可将流分为字节流和字符流。1.字节流 2.字符流,其中字节流中数据以8位的字节为单元进行读写,字符流数据以16位的字符为单位进行读写。

Java中流主要分为4大家族:InputStream,OutputStream,Reader,Writer.

1.字节流

​ InputStream类和OutputStream类是字节流的两个顶层父类。它们提供了输入流类与输出流类的通用API。InputStream类和OutputStream类都是抽象类。

InputStream类的子类有:AudioInputStream,SequenceInputStream,FileInputStream,ObjectInputStream,ByteArrayInputStream,PipedInputStream,FilterInputStream。

InputStream类主要方法如下:

int read();     //从流中读出一个字节的数据,没有返回-1.
int read(byte b[]);   //从流中读取数据存放到字节数组b中。返回读取字节数,没有返回-1.
int read(byte b[], int off, int len);
/* 从流中读取len个字节的数据存放到字节数组b下标off的起始位置中。*/ 
long skip(long n);     //跳过流中若干字节数
int available();      //返回流中可用字节数
void mark(int readlimit)    //在流中标记一个位置
void reset()      //返回标记过的位置
boolean markSupport()     //是否支持标记和复位操作
void close()        //关闭流

​ FilterInputStream类有9个直接子类,它们提供对输入流数据过滤或转换的更多的特殊方式。

BufferedInputStream
DataInputStream
CheckedInputStream
CipherInputStream
DigestInputStream
InflaterInputStream
LineNumberInputStream
ProgressMonitorInputStream
PushbackInputStream

System.out.println(""); = PrintStream.println(""); //标准的输出流(输出到控制台)

2.字符流

​ 流根据读取数据的方式可以分为:字节流和字符流,字节流是按照字节的方式读取,字符流是按照字符的方式读取,一次读取两字节。因为Java中一个字符占2字节。

字节流适合读取:视频,声音,图片等二进制文件,

字符流适合读取:纯文本文件。

//写入文件
public class Filetest(){
	
	public static void main(String[] args) throws Exception{
	
		FileWriter fw = new FileWriter("a.txt",true); //追加
		fw.write("Hello");
		
		fw.flush();//刷新
		fw.close();//关闭流
	}

}

//读入文件

public Test2{
	public static void main(String args[]){
		char[] c= new char[512];//刚好1KB
		int tem=0;
		try{
			FileReader fr = new FileReader("a.txt"); //当前路径下的txt文件
			while((tem=fr.read(c)) != -1){
				System.out.print(new String(c,0,tem))
			} 
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			try{
				if(fr!=null)
					fr.close();
			}catch(Exception e){
				e.printStackTrace();
			}
			
		}
		
		
	
	}

}

代码给上,请自行体会。

代码中每个文件操作都有异常处理操作是因为,这些异常不是RuntimeException类的异常,java必须捕获这些异常,因为这些异常是由于外界的原因导致程序的中断,所以必须捕获。在上面的异常处理那章已经有说明,所以就不再进行重复。

24.总结

​ 以为Java涉及的基础知识比较广,所以这里只是粗略的介绍了一下,其实就是自己粗略的记录一下笔记。很多细节上的问题根本没有进行记录,如果想知道还是其各位购买相关的书籍和教程来进行学习。如有错误,请各位提出。

猜你喜欢

转载自blog.csdn.net/qq_43203949/article/details/105313041
今日推荐