JAVA复习笔记
-
第一章
Java语言1990创建,于1995年正式发布。
Java虚拟机可以运行的文件类型为类文件 (class 文件)
java跨平台机制是由什么实现的:看这篇博客
配置Java环境时,classpath和path的作用:
path作用是指定命令搜索路径,在命令行下面执行命令如javac编译java程序时,它会到path变量所指定的路径中查找看是否能找到相应的命令程序。我们需要把jdk安装目录下的bin目录增加到现有的path变量中,bin目录中包含经常要用到的可执行文件如javac/java/javadoc等,设置好path变量后,就可以在任何目录下执行javac/java等工具了。classpath环境变量的作用是指定类搜索路径,要使用已经编写好的类,前提当然是能够找到它们了,JVM就是通过classpath来寻找类的。我们需要把jdk安装目录下的lib子目录中的dt.jar和tools.jar设置到classpath中,当然,当前目录“.”也必须加入到该变量中。
-
第二章
逻辑运算中的短路特点(惰性计算):Java中有&&运算和 | | 运算,那么如果Java虚拟机发现&&左方的表达式为false,则它不需要也不会去计算&&右方表达式才知道要返回false。同理,如果Java虚拟机发现 | | 左方的表达式为true,则它不需要也不会去计算 | | 右方表达式才知道要返回true。
采用的字符集,理论上能表示的符号个数。
unicode编码是固定长度的,16位,也就是2两个字节代表一个字符,这样一共可以表示65536个字符。八种基本数据类型的名称、长度、表达范围、缺省值。
-
第三章
类构造器(构造函数)的写法:
构造器用来创建对象并赋予其初值,生成新对象时,调用构造器方法创建并初始化新对象。
构造器名字与其类的名字相同,且定义构造器时,无须指定其返回类型,且构造器会对所有实例变量赋值。
只有在创建对象时,才会调用构造器;而修改对象不能用构造器,要用相应的设置方法去修改对象的值。
如果一个构造器没有参数,则称之为缺省构造器。构造器总结:
构造器是一种通过使用new操作符创建类的对象时调用的方法。
构造器为新创建的对象提供了实例变量的初始值。
构造器必须与它们所属的类具有相同的名字。
构造器的定义与其他方法一样,只是它们的方法头中没有返回类型,甚至没有void。包
包就是类的集合,这些类被群组在一个文件夹中,该文件名就是包名。那么这个文件夹里面的文件在头部需要写 package 包名,在这个语句前只可以是注释或空行。
package作用:
包是群组在同一个文件夹中并赋予了包名的类的集合,每个类都处于以该类命名的单独的文件中。包中的每个文件在忽略空行和注释后,都必须以一条package语句开头。import作用:
在任何程序或类的定义中,通过在包含该程序或类定义的文件开头处放置一条import语句,就可以使用这个包中的所有类。该程序或类无须和包中的类位于同一个文件夹中。
使用语法:import 包名.类名(记得包名在前面,用.再加类名),如果是想使用包中所有类,则使用*,如:import java.io.*;(星号表示想要导入该包中所有的文件)static三个位置上的不同含义
static修饰成员方法:static修饰的方法称为静态方法,静态方法独立存在,不需要通过对象才能去访问,也就是不依附于任何对象,也没有this,可以直接调用该方法。需要注意的是,静态方法里不可以调用非静态方法,但是反过来可以。
static修饰成员变量:同上述一样,被称为静态变量。静态变量被所有对象共享,只有一个版本(如果不是静态变量,那么每一个对象都有自己版本的变量)。
static修饰代码块:static修饰的代码块只会执行一次,也就是程序一开始加载的时候执行一次。静态代码块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来依次执行每个static块。重载
重载和重写的区别final的三个位置上的不同含义:
final声明变量之后,该变量不可改其值。变为常量。
final修饰后的方法不可被重写,其实private相当于隐式final,因为private方法子类无法访问,自然也就无法覆盖。final修饰为了子类不可重写该方法。
final修饰后的类不可被继承。如果希望一个类不允许任何类继承,并且不允许其他人对这个类有任何改动,可以将这个类设置为final形式。
如果将某个类设置为final形式,则类中的所有方法都被隐式设置为final形式,但是final类中的成员变量可以被定义为final或非final形式。
注意:如果构造器调用一个共有方法,但是该方法被派生类覆盖,那么这样会出错,应该将这个共有方法声明为最终方法(final)abstract三个位置上的不同含义:
抽象类:抽象类无法创建该类的对象,其只能作为基类,故抽象类也可被称为抽象基类。如果一个类中有一个抽象方法,那么该类就应该声明为抽象类,故一个抽象类中并不是所有方法都是抽象方法。
抽象方法:一定在抽象类中,抽象方法没有方法体,只有方法声明,交由继承抽象类(父类)的子类去重写。若子类将父类的所有抽象方法重写,则子类“实例化”,否则子类仍为抽象类。抽象方法没有主体(也就是没有{}),需要注意的是,抽象方法不能用private和static修饰。继承:继承相关博客
接口(是一种引用类型)
接口用interface来代替class,也就是变成 public interface 接口名。接口可以包含任意数量的公有方法头,每个方法头后面都跟着一 个分号。接口需要存储在独有的文件中,文件名为 接口名.java。
例:
/**
一个静态方法的接口,该方法用于转换英尺与英寸之间的测量值。
*/
public interface Convertible{
public static final int INCHES_PER_FOOT=12;
public static double convertToInches(double feet);
public static double convertToFeet(double inches);
}
接口的实现:一个类要实现一个接口,则需要类的定义后面加上implements
接
口
名
1
接口名_1
接口名1,
接
口
名
2
接口名_2
接口名2,如
public class Rectangle implements Measurable//接口Measurable的一个实现
如果类欲实现一个接口,那么必须将接口中所有的方法都给出自己的定义,类中可以定义接口中没有出现的方法体。
一个接口可以被多个类实现,每个类都有自己的实现。一个类也可以实现多个接口。
方法的参数可以是接口类型,如:
public static void display(Measurable figure){
double perimeter=figure.getPerimeter();
double area=figure.getArea();
}
display方法的参数为接口类型,这个时候有:
Measurable box=new Rectangle(5.0,5.0);
Measurable disc=new Circle(5.0);
这里box和disc为接口类型,也就是引用类型,引用的是Rectangle类的对象和Circle类的对象,那么如果有如下程序:
display(box);
display(disc);
那么调用的是Rectangle类和Circle类中的各自类中定义的方法,也就是自己定义的getPerimeter和getArea方法。
接口类型的变量可以引用任何实现了该接口的类的对象,但是该对象自身总是会确定针对每个方法名应该执行哪种方法行为。
再来一条程序:Measurable m=new Circle(5.0);
这里Circle类是实现了接口Measurable 的,但是在使用m这个变量时,只能调用出现在Measurable中的方法,除非我们进行强制类型转换:
Circle c=(Circle)m;
System.out.println(c.getCircumference());
System.gc()
System.gc()这个函数的作用只是提醒虚拟机:程序员希望进行一次垃圾回收。但是它不能保证垃圾回收一定会进行,而且具体什么时候进行是取决于具体的虚拟机的,不同的虚拟机有不同的对策。而没有被任何可达变量指向的对象(也就是找不到的对象)就可能被回收。system.gc()和system.runFinalization()区别作用
- 第四章
数组(引用类型)
创建数组:double[] arr=new double[10];
我们创建了10个double类型的变量集合类型构成的数组。数组的基类型可以任意,可以是类类型。
语法为:Base_Type[] Array_Name=new Base_Type[Length];
数组的长度一旦声明,就无法更改,(因为数组长度为final变量)。例:
Species[] entry=new Species[20];
entry.length=10;//非法!
数组在声明时,如果不给初始值,那么默认值为0。
数组是对象,如果有两个数组a和b,那么a有值,b未赋值。如果这时候加这么一条语句:b=a;
那么b就跟a一样,甚至当你对a[2]赋值为100,那么b[2]也被赋值为了100.
所以一般不用
=
=
= 对数组进行相关操作,并且== 对数组进行操作时,判等操作符 == 会测试两个数组是否存储在计算机内存中相同的位
置上。尽管有两个数组长度一样,每个位置上的值和数据类型都一样,但是它们在内存的位置不同。
疑难杂症:对数组使用操作符=和 == 可以使用赋值操作符=赋予一个数组多个名字,但是不能使用它将一个数组的内容复制给另一个不同的数组。类似地,判等操作符==测试的是两个数组名引用的是否是相同的内存地址,它不会测试两个不同的数组是否包含相同的值。
Java创建数组的几种方式
创建二维甚至多维数组:
字符串
使用+操作符(连接操作符)来执行字符串之间的连接。
字符串相关操作:
包装器类
包装器类的相关博客,都很详细。
包装器类
包装器类是什么
如果有兴趣,可以看 为什么要有包装器类
- 第五章
泛型
Java允许类定义包含表示数据类型的参数,这些参数称为泛型。类和方法可以使用类型参数来代替具体的数据类型。泛型使得我们可以在使用类或方法时参数化数据类型,程序员可以将任意的类类型插入类型参数,以产生针对这种特定实例的具体的类类型或方法。(相当于c里面的template< class T >)例:
public class Sample<T>
{
private T data;
public void setData(T newValue){
data=newValue;
}
public T getData(){
return data;
}
}
我们在类定义中使用类型参数的方式与使用实际类类型的方式相
同,只是无法将其与new一起使用。
Sample<String> anObject=new Sample<String>();
anObject.setData("Hello");
当创建具有类型参数的类的对象时,不能插入像int、double或
char这样的基本类型。例如,下面的语句会导致语法错误:ArrayList<int> aList=new ArrayList<int>(20);//非法!
假如现在有一个类,我们进行了泛化:public class Sample<E>{ ... }
那么这个类的构造器我们不需要在后面加上泛化,也就是我们直接这么写就好:public Sample(){...}
因为构造器是内部类,可以访问外部类的类型参数。
for的简化写法:for(n=1,count=1;n<=10;n++)count*=n;
还可以进一步简化为for(n=1,count=1;n<=10;count*=n,n++);
tips:在写循环语句时,如果确保自己的程序至少会执行一次,那么可以选择do-while语句,如果用for语句不太好理解程序,那么可以用while语句,当然怎么使用是自由的,没有硬性要求。
- 第六章
异常
异常是表示在程序执行过程中发生异常事件的对象。创建这个对象的过程(即产生异常)称为抛出异常。
在Java中处理异常的基本方式是包含try-throw-catch三元组。
try的格式:
try
{
Code_To_Try
Possibly_Throw_An_Exception
More_Code
}
抛出异常的语句可以这么写:throw new Exception("Exception:No milk!");
而相应catch可以这么写:
catch(Exception e)
{
System.out.println(e.getMessage());
More_Code...
}
当抛出异常时,包围它的块中的代码就会停止执行,另一部分代码(即被称为catch块的代码)则开始执行。执行catch块称为捕获异常。当抛出异常时,它最终应该被某个catch块所捕获。
如果try块里抛出了异常或是try块里的方法抛出了异常,那么程序从try块里跳出,去找对应的catch块去调用,catch块执行完之后,从最后一个catch块(比如有catch1~catch5,try中抛出的异常在catch2中被处理,那么处理完之后,程序执行catch5后面的代码)下面的程序开始执行(try和catch之间的代码被跳过)。
对象在String类型实例变量中携带的消息。这个字符串可以通过调用访问器方法getMessage来找回。该字符串允许我们的代码将一条消息随异常对象一起发送,使得catch块可以找回该消息。
最好自己定义异常,自定义异常如果我们没有正当的理由使用其他类作为基类,那么使用Exception作为基类。我们应该至少定义两个构造器,包括缺省构造器和有单个String参数的构造器。如:
public class TidalWaveException extends Exception
{
public TidalWaveException()
{
super("Tidal Wave Exception thrown!");
}
public TidalWaveException(String message)
{
super(message);
}
}
finally块:
try
{
...
}
Catch_Block(s)
finally
{
Some_Code//总是执行
}
-
第七章
System.in 和System.out所属的类为System类,System类内部包含in、out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
PrintWriter类详解 和 Scanner类常用的方法向二进制文件中写入基本类型值:
创建二进制文件
try
{
//打开文件
ObjectOutputStream Output_Stream_Name=
new ObjectOutputStream(new FileOutputStream(File_Name));
//使用以下形式的语句写入文件
Output_Stream_Name.MethodName(Argument);//具体的方法见上图
//记得关闭文件
Output_Stream_Name.close();
}
catch(FileNotFoundException e)
{
Statements_Dealing_With_The_Exception
}
catch(IOException e)
{
Statements_Dealing_With_The_Exception
}
从二进制读取
transient关键字
1、变量被transient修饰,变量将不会被序列化
2、transient关键字只能修饰变量,而不能修饰方法和类
3、被static关键字修饰的变量不参与序列化,一个静态static变量不管是否被transient修饰,均不能被序列化
4、final变量值参与序列化,final transient同时修饰变量,final不会影响transient,一样不会参与序列化
结语:transient修饰的优点是节省存储空间,但是transient修饰的字段会重新计算,重新初始化。
-
第八章
JOptionPane类 -
第十章
几种注释:单行注释//
多行注释/* 注释内容*/
文档注释/** 注释内容*/
assert断言