Java基础知识笔记

1 例子

每一个Java源文件只能有一个public类。当有一个public类时,源文件名必须和类名相同。

main()方法想要运行也不必在public类中,但是必须在类名和源文件相同的类中

 

public class HollowWorld  

{

public static void main(String[] args)

{

  System.out.println(“Hollow World”);

}

}

2 线程

在Java语言中 线程是一种特殊的对象,它必须由Thread类或其子孙类来创建。

  1. 使用构型为Thread(Runnable)的构造子将一个实现了Runnable接口的对象包装成一个线程
  2. 从Thread类派生出子类并重写run方法,使用该子类创建的对象即为线程。\

3 java的基本语法

大小写敏感;

类的首字母必须大写,若类名由若干个单词组成,则每个字母的首字母应该大写;

所有方法名都应该以小写字母开头,若含有若干个单词,则后面的单词首字母大写;

源文件名:源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记Java是大小写敏感的),文件名的后缀为.java。(如果文件名和类名不相同则会导致编译错误);

主方法入口:所有的Java 程序由public static void main(String []args)方法开始执行。

4 Java标识符

所有的标识符都因该以字母,美元符$,下划线开始;

标识符只能有字母,美元符$,下划线以及数字。

5 利用继承的方法

可以利用已经存在的类的方法和属性,而不用重写这些代码。被继承的类称为超类(superclass),派生类称为子类(subclass)。

6 接口

在Java中,接口可以理解为对象间相互通信的协议。

接口在继承中扮演很重要的角色;

接口只定义派生要用到的方法,但是方法的具体实现完全取决于派生类。

7 软件对象的状态就是属性,行为通过方法体现

在软件开发中,方法操作对象内部的状态改变,对象的相互调用也是通过方法来完成的。

8 构造方法

每个类都有构造方法。如果没有显式的为类定义构造方法,Java编译器将会为该类提供一个默认构造方法。在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法。

9 对象的创建

使用关键字new 先声明一个对象的名称,对象的类型;

然后使用关键字new 来实例化(创建)一个对象;

最后初始化:使用new 创建对象时,会调用构造方法初始化对象。

10 访问实例化变量和方法

通过已经创建的对象来访问成员变量和成员方法;

实例化对象: ObjectReference=new Constructor();

访问其中的变量: ObjectReference.variableName;

访问类中的方法:ObjectReference.MethodName();

11 Java包

包主要用来对类和接口进行分类。,当开发Java程序时,可能编写成百上千的类,因此很有必要对类和接口进行分类。

12 Import语句

在Java中,如果给出一个完成整的限定名,包括包名,类名,那么Java编译器就可以很容易的定位到源代码或者类。Import语句就是来提供一个合理的路径,使得编译器可以找到某个类。

Java基本数据类型

1 内置数据类型

四个整型,两个浮点型,一个布尔型,一个字符型。

byte   short  int   long   Boolean  float  double  char

2 引用数据类型

在Java中,引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定一个特定的类型,比如Employee,Puppy等。变量一旦声明后,类型就不能被改变了。

对象,数组都是引用数据类型。

所有的引用类型的默认值都是null

一个引用变量可以用来引用与任何与之兼容的类型

3 常量

在Java中使用final关键字来修饰常量,声明方式与变量类似;

Byte int long short 都可以使用十进制,十六进制以及8进制的方式来表示;

当使用常量时,前缀0表示8进制,而前缀0x代表16进制。

4 数据类型转换原则

  • 能对boolean类型进行类型转换
  • 不能把对象类型转化为不相关类的对象
  • 在把容量大的类型转化为容量小的类型时必须使用强制类型转换。
  • 转换过程中可能导致溢出或精度损失。
  • 浮点数到整数的转换是通过舍弃小数得到的,而不是四舍五入。
  • 自动转换必须满足转换前的数据类型的位数要低于转换后的数据类型。

5强制类型转换

条件是转换的数据类型必须是兼容的;

格式 : (type)value

6 隐含强制类型转换

整数的默认类型是int;

浮点型不存在这种情况,因为在定义float类型时必须是在数字后边跟上F或f。

java变量类型

1 Java语音支持的变量类型

类变量:独立于方法之外的变量,用static修饰

实例变量:独立于方法之外的变量,不过没有static修饰

局部变量:类方法中的变量

2 局部变量:是栈上分配的

局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。

3 实例变量

实例变量声明在一个类中,但在方法、构造方法和语句块之外

实例化变量的值应该至少被一个方法、构造方法或语句块引用;

实例化变量可以声明在使用前或者使用后;

访问修饰符可以修饰实例变量;

实例变量具有默认值,数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明前指定,也可以在构造方法中指定。

4 类变量(静态变量)

类变量在类中以static关键字声明,但必须在方法构造方法和语句块之外。

静态变量可以通过:ClassName.VariableName的方式访问

设置静态常量时,即:public static final 时类变量的名称建议使用首字母大写。

 

5 src

软件中src 的意思是source,也就是源代码的意思

6 静态变量和实例变量的区别

静态变量属于类,该类不产生对象,通过类名可以调用静态变量

实例变量属于该类的对象,必须产生该类对象,才能调用实例变量

总之,实例变量必须通过创建对象后才可以通过这个对象来引用,静态变量可以直接通过类名来引用。

Java修饰符

修饰符用来定义类,方法或者是变量,通常放在语句的最前端。

1 访问修饰符

分为以下几种情况

default  在同一包内可见,不使用任何修饰符

private  在同一类内可见 使用对象:变量,方法

私有访问修饰符是最严格分访问级别,所以被声明为private的方法、变量和构造方法只能被所属类访问,且接口和类不能声明为private。

声明为私有访问类型的变量只能通过类中的公共getter方法来被外部类访问

public   对所有类可见。适用对象:类,接口、变量、方法。

如果几个相互访问的public类分布在不同的包中,则需要导入

Protected  对同一包内的类和所有子类可见。使用对象:变量,方法

被声明为protected的变量、方法和构造器能被同一个包中的任何其他类访问,也能被不同包中的子类访问。

修饰符

当前类

同一包内

子孙类

其他包

Public

Y

Y

Y

Y

Protected

Y

Y

Y

N

Default

Y

y

N

N

Private

Y

n

n

n

2 被访问和继承

继承规则

父类中声明为public的方法在子类中也必须为public

父类中声明为protected的方法在子类中要么声明为protected,要么声明为public,不能声明为private

父类中声明为private的方法,不能被继承。

3 非访问修饰符

static 静态变量,访问方式:classname.variablename

静态方法 访问方式:classname.methodname()

循环和选择

1 for循环

虽然所有循环结构都可以用 while 或者 do...while表示,但 Java 提供了另一种语句 —— for 循环,使一些循环结构变得更加简单。

for循环执行的次数是在执行前就确定的。语法格式如下:

for(初始化; 布尔表达式; 更新) { //代码语句 }

关于 for 循环有以下几点说明:

最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。

然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。

执行一次循环后,更新循环控制变量。

再次检测布尔表达式。循环执行上面的过程。

3 break

break 主要用在循环语句或者是switch语句中,用来跳出整个语句块。

break 跳出最里层的循环,并且继续执行该循环下面的语句。

2 for循环数组

for(声明语句 : 表达式) { //代码句子 }

4 continue

适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环迭代

在for循环中,continue语句使程序立即跳转到更新语句。

在while或者是do….while循环中,程序立即跳转到布尔表达式的判断语句。

5 switch语句

switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE 7 开始,switch 支持字符串类型了,同时 case 标签必须为字符串常量或字面量。

switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值和冒号。

case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。

当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。

当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。

switch 语句可以包含一个 default 分支,该分支必须是 switch 语句的最后一个分支。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。

6 日期

Java.util包提供了Date类来封装当前的时间和日期。

7 休眠

sleep()使得当前线程进入停滞状态(阻碍当前线程),让出CPU的使用、目的是不让当前线程独自霸占该进程所获得的CPU资源,以留一定时间给其他线程执行的机会。

8 创建格式化字符串

String 类使用静态方法 format() 返回一个String 对象而不是 PrintStream 对象。

String 类的静态方法 format() 能用来创建可复用的格式化字符串,而不仅仅是用于一次打印输出

如下所示:

System.out.printf("浮点型变量的值为 " + "%f, 整型变量的值为 " + " %d, 字符串变量的值为 " + "is %s", floatVar, intVar, stringVar);

你也可以这样写

String fs; fs = String.format("浮点型变量的值为 " + "%f, 整型变量的值为 " + " %d, 字符串变量的值为 " + " %s", floatVar, intVar, stringVar);

9 String 类是不可改变的解析

String s = "Google";

System.out.println("s = " + s);

 

s = "Runoob";

System.out.println("s = " + s);

输出结果为:

Google

Runoob

从结果上看是改变了,但为什么门说String对象是不可变的呢?

原因在于实例中的 s 只是一个 String 对象的引用,并不是对象本身,当执行 s = "Runoob"; 创建了一个新的对象 "Runoob",而原来的 "Google" 还存在于内存中。

10 Java StringBuffer 和 StringBuilder 类

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

Test.java 文件代码:

public class Test{

 public static void main(String args[]){

 StringBuffer sBuffer = new StringBuffer("菜鸟教程官网:");

 sBuffer.append("www");

 sBuffer.append(".runoob");

 sBuffer.append(".com");

System.out.println(sBuffer);

} 

}

11 GregorianCalendar类

Calendar类实现了公历日历,GregorianCalendar是Calendar类的一个具体实现。

Calendar 的getInstance()方法返回一个默认用当前的语言环境和时区初始化的GregorianCalendar对象。GregorianCalendar定义了两个字段:AD和BC。这是代表公历定义的两个时代。

Java方法

1 命名规则

必须以字母、下划线、$开头。

可以包括数字,但是不能以他开头。

2 方法的调用

当程序调用一个方法时,程序的控制权交给了被调用的方法。当被调用方法的返回语句执行或者到达方法体闭括号时候交还控制权给程序。

当方法返回一个值时,方法调用通常被当作一个值

当方法返回值是void时,方法调用的一定是一条语句。

3 构造方法

当一个对象被创建时候,构造方法用来初始化该对象。构造方法和它所在类的名字相同,但构造方法没有返回值。

通常会使用构造方法给一个类的实例变量赋初值,或者执行其它必要的步骤来创建一个完整的对象。

不管你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个默认构造方法,它把所有成员初始化为0。

一旦你定义了自己的构造方法,默认构造方法就会失效。

构造方法前什么都不加,如void 。否则构造方法就变成普通方法了。

4 可变参数

可变参数声明方法:typeName…parameterName

在方法声明中,指定参数类型后加一个省略号(…)

一个方法中只能指定一个可变参数,他必须是方法的最后一个参数。任何普通参数的声明必须在它之前。

5 方法的调用

如果方法返回值是void,方法调用一定是一条语句。

当方法返回一个值的时候,方法调用通常被当做一个值。

调用一个方法时候需要提供参数,你必须按照参数列表指定的顺序提供。

方法重载:就是说一个类的两个方法拥有相同的名字,但是有不同的参数列表。

方法的参数范围涵盖整个方法。参数实际上是一个局部变量。

命令行参数是在执行程序时候紧跟在程序名字后面的信息。

Java流(Stream)、文件(File)和IO

1 简介

Java.io包几乎包含了所有的输入输出需要的类。所有这些流代表了输入源和输出目标。

Java.io包中的流支持很多格式,比如:基本类型、对象、本地化符集等等。

一个流可以理解为一个数据的序列。输入流表示从一个数据源读取数据,输出流表示向一个目标写数据。

2 读取控制台输入

Java的控制台输入由System.in完成。

为了获得一个绑定到控制台的字符流,你可以把System.in包装在一个BufferedReader对象中来创建一个字符流。

BufferedReader br=new BufferedRead(new InputStreamReader(System.in));

BufferedReader 对象创建后,我们便可以使用 read() 方法从控制台读取一个字符,或者用 readLine() 方法读取一个字符串。

// 使用 BufferedReader 在控制台读取字符 

import java.io.*;

 public class BRReadLines {

    public static void main(String args[]) throws IOException { 

// 使用 System.in 创建 BufferedReader

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

 String str;

        System.out.println("Enter lines of text.");

System.out.println("Enter 'end' to quit.");

    do {

       str = br.readLine();

System.out.println(str);

} while(!str.equals("end"));

} 

}

3 控制台输出

控制台的输出由print()和println()完成。这些方法都由PrintSream定义,System.out是该类对象的一个引用。

4 读写文件

FileputStream: 该流用于从文件读取数据,他的对象可以用关键字new来创建

             有多种构造方法可用来创建对象。

             可以使用字符串类型的文件名来创建一个输入流对象来读取文件:

InputStream f = new FileInputStream("C:/java/hello");

也可以使用一个文件对象来创建一个输入流对象来读取文件。我们首先得使用 File() 方法来创建一个文件对象:

File f = new File("C:/java/hello");

InputStream out = new FileInputStream(f);

FileOutputStream:该类用来创建一个文件并向文件中写数据。

如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。

有两个构造方法可以用来创建 FileOutputStream 对象。

使用字符串类型的文件名来创建一个输出流对象:

OutputStream f = new FileOutputStream("C:/java/hello")

也可以使用一个文件对象来创建一个输出流来写文件。我们首先得使用File()方法来创建一个文件对象:

File f = new File("C:/java/hello");

OutputStream f = new FileOutputStream(f);

5 Scanner类

next()和nextLine()的区别

next()

1一定要读取到有效字符后才可以输入

2在输入有效字符之前遇到空白,next()方法会自动将其去掉。

3只有输入有效字符后才将其后面输入的空白字符作为分隔符或者结束符

4不能得到带有空格的字符串

nextLine()

1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。

2、可以获得空白。

如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:

例如

if(scan.hasNextInt()){                 

      // 判断输入的是否是整数  

            i = scan.nextInt() ;                

      // 接收整数  

            System.out.println("整数数据:" + i) ;  

        }else{                                 

      // 输入错误的信息  

            System.out.println("输入的不是整数!") ;  

        }  

 

6 Java流与文件操作

一、   数据流的基本概念

1.数据流

在Java中把不同的数据源与程序之间的数据传输都抽象表述为“流”(stream),以实现相对统一和简单的输入/输出操作方式。传输中的数据就像流水一样,也称为数据流。

2 .I/O数据流的分类方式

数据流分为输入流和输出流两类。输入流只能读取不能写。而输出流只能写不能读。(这里站在程序的角度来确定出入方向,即将数据从程序外部传送到程序中谓之“输入”数据,将程序中的数据传送到外部谓之“输出”数据。

3.缓冲流(Buffered Stream)

对数据流的每次操作都是以字节为单位进行的,既可以向输出流写入一个字节,也可从输入流中读取一个字节。显然效率太低,通常使用缓冲流,即为一个流配置一个缓冲区,一个缓冲区就是专门传送数据的一块内存。

4.数据源(Data Source):是指那些能够提供数据的地方,包括键盘、磁盘文件、网络接口等。

5.数据宿(Data Sink):指能够接收数据的地方,可以是磁盘文件、网络接口以及显示器、打印机等外部设备。(数据宿也可认为是数据传输的目的地)

Java异常处理

异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的

异常发生的原因有很多,通常包含以下几大类:

用户非法数据

要打开的文件不存在

网络通信时链接中断,或者JVM内存溢出。

1 要掌握的三种异常

检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。

运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。

错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

2 Exception类的层次

所有的异常类是从java.lang.Excrotion类中继承的子类。

Exception类是Throwable类中的子类。除了Exception类外,Throwable还有一个子类Error。

Java程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。

Error用来指示运行时环境发生的错误。

3 finally关键字

finally 关键字用来创建在 try 代码块后面执行的代码块。

无论是否发生异常,finally 代码块中的代码总会被执行。

在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。

4 注意下面事项:

catch 不能独立于 try 存在。

在 try/catch 后面添加 finally 块并非强制性要求的。

try 代码后不能既没 catch 块也没 finally 块。

try, catch, finally 块之间不能添加任何代码。

5 声明自定义异常

在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。

所有异常都必须是 Throwable 的子类。

如果希望写一个检查性异常类,则需要继承 Exception 类。

如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。

可以像下面这样定义自己的异常类:

class MyException extends Exception{

}

只继承Exception 类来创建的异常类是检查性异常类。

下面的 InsufficientFundsException 类是用户定义的异常类,它继承自 Exception。

一个异常类和其它任何类一样,包含有变量和方法。

6 通用异常

在Java中定义了两种类型的异常和错误。

JVM(Java虚拟机) 异常:由 JVM 抛出的异常或错误。例如:NullPointerException 类,ArrayIndexOutOfBoundsException 类,ClassCastException 类。

程序级异常:由程序或者API程序抛出的异常。例如 IllegalArgumentException 类,IllegalStateException 类。

7 catch代码块儿中

1)e.getMessage()函数:输出错误性质

2)e.toString()函数:给出异常的类型和性质

3)printStackTrace()函数:指出异常的类型、性质、栈层次及出现在程序中的位置

Java的继承

1 继承的格式

Java通过extends关键字可以声明一个类是从另外一个类继承而来

class 父类 { }

 class 子类 extends 父类 { }

2 继承的特性

  • 类可以拥有父类非private的属性,方法;
  • 子类可以拥有自己的父类和方法,即子类可以对父类进行扩展
  • 子类可以用自己的方法实现父类的方法。
  • Java的继承是单继承,但是可以多重继承。单继承是一个子类只能有一个分类,

多重继承是A继承B,B继承C以此接力,这是Java区别于C++继承的一个特性。

  • 高了类之间的耦合性(继承的缺点,耦合度高会造成代码之间的联系)

3 继承关键字

Java中继承可以使用extends和implements这两个关键字来实现继承,而且所有的类都继承于java.lang.Obejct。当一个类没有继承的两个关键字,则默认object(这个类在java.lang 包中,所以不需要import)祖先类。

extends关键字在Java中类的继承是单继承,所以,extends只能继承一个类。

implements关键字:使用implements关键字可以变相的使Java具有多继承的特性,使用范围是类的接口的情况,可以同时继承多个接口(接口与接口之间用逗号分开)

super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前父类的对象。

super 语句必须是子类构造方法的第一条语句。

不能在子类中使用父类构造方法名来调用父类构造方法。

父类的构造方法不被子类继承。调用父类的构造方法的唯一途径是使用 super 关键字,如果子类中没显式调用,则编译器自动将 super(); 作为子类构造方法的第一条语句。这会形成一个构造方法链。

静态方法中不能使用 super 关键字

如果是继承的方法,是没有必要使用 super 来调用,直接即可调用。但如果子类覆盖或重写了父类的方法,则只有使用 super 才能在子类中调用父类中的被重写的方法。

this 关键字:指向自己的引用。

调用当前类的构造方法,并且必须是方法的第一条语句。如:this(); 调用默认构造方法。this(参数); 调用带参构造方法。

限定当前对象的数据域变量。一般用于方法内的局部变量与对象的数据域变量同名的情况。如 this.num = num。this.num 表示当前对象的数据域变量 num,而 num 表示方法中的局部变量。

final关键字:声明类可以把类定义为不能继承的,即最终类;

            多用来修饰方法,该方法不能被子类继承。

4 构造器

子类不能继承父类的构造器(构造方法或构造函数),但父类的构造器带有参数的,则必须在子类的构造器中显示地通过super关键字调用父类的构造器并配以适当的参数列表

如果父类有无参数构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器

5 继承注意事项

同一个包内不能定义同姓名的两个类

Java重写(Override)与重载(Overload)

1重写(Override)

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。

在面向对象原则里,重写意味着可以重写任何现有方法

2方法的重写规则

参数列表必须完全与被重写方法的相同;

返回类型必须完全与被重写方法的返回类型相同;

访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。

父类的成员方法只能被它的子类重写。

声明为final的方法不能被重写。

声明为static的方法不能被重写,但是能够被再次声明。

子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。

子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。

重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。

构造方法不能被重写。

如果不能继承一个方法,则不能重写这个方法。

3 Super关键字的使用

当需要在子类中调用父类的被重写方法时,要使用super关键字。

4重载(Overload)

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

最常用的地方就是构造器的重载。

重载规则

被重载的方法必须改变参数列表(参数个数或类型或顺序不一样);

被重载的方法可以改变返回类型;

被重载的方法可以改变访问修饰符;

被重载的方法可以声明新的或更广的检查异常;

方法能够在同一个类中或者在一个子类中被重载。

无法以返回值类型作为重载函数的区分标准。

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

Java多态与封装

1 多态

是同一个行为具有多个不同表现形式或形态的能力

多态的优点

1. 消除类型之间的耦合关系

2. 可替换性

3. 可扩充性

4. 接口性

5. 灵活性

6. 简化性

多态存在的三个必要条件

继承

重写

父类引用指向子类对象

比如:

Parent p = new Child();

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

2 抽象方法

如果一个类包含抽象方法,那么该类必须是抽象类。

任何子类都必须重写父类的抽象方法,或者声明自身为抽象类。

继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。

3 抽象类总结规定

1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

4. 构造方法,类方法(用static修饰的方法)不能声明为抽象方法。

5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

4 Java封装

在面向对象程式设计中,封装(英语:Encapsulation)是指一种抽象性函式接口的实现细节部分包装、隐藏起来的方法。

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

要访问该类的代码和数据,必须通过严格的接口控制。

封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。

适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

5 封装的优点

良好的封装能够减少耦合

类内部的结构可以自由修改

可以对成员变量进行更精准的控制

隐藏信息,实现细节。

Java接口

让我们来看一个java封装类的例子:

6EncapTest.java 文件代码

/* 文件名: EncapTest.java */ 

public class EncapTest{ 

private String name;

private String idNum;

private int age;

public int getAge(){ return age; } 

public String getName(){ return name; }

public String getIdNum(){ return idNum; } 

public void setAge( int newAge){ age = newAge; } 

public void setName(String newName){ name = newName; }

  public void setIdNum( String newId){ idNum = newId; } 

}

以上实例中public方法是外部类访问该类成员变量的入口。

通常情况下,这些方法被称为getter和setter方法。

因此,任何要访问类中私有成员变量的类都要通过这些getter和setter方法。

 

接口

接口(interface),在Java编程语言中是一个抽象类型,是抽象方法的集合,接口通常用interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

接口无法被实例化,但可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则必须声明为抽象类。另外,在Java中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个一次接口实现的对象。

1 接口与类相似点

一个接口可以有多个方法

接口文件保存在.java结尾的文件中,文件名使用接口名

接口的字节文件保存在.class结尾的文件中

接口相应的字节代码文件必须在与包名称相匹配的目录结构中

2 接口与类的区别

接口不能实例化对象

接口没有构造方法

接口中左右的方法必须是抽象方法

接口不能包含成员变量,除了static和final变量

接口不是被类继承了,而是要被类实现。

接口支持多继承。

3 接口特性

接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。

接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。

接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。

接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。

接口中的方法都是公有的。

4 抽象类和接口的区别

抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。

抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。

接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。

一个类只能继承一个抽象类,而一个类却可以实现多个接口。

5 接口的实现

当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。

实现一个接口的语法,可以使用这个公式:

...implements 接口名称[, 其他接口, 其他接口..., ...] ...

6 重写接口中声明的方法时,需要注意以下规则:

类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。

类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。

如果实现接口的类是抽象类,那么就没必要实现该接口的方法。

7 在实现接口的时候,也要注意一些规则:

一个类可以同时实现多个接口。

一个类只能继承一个类,但是能实现多个接口。

一个接口能继承另一个接口,这和类之间的继承比较相似。

8 接口的继承

一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。

9 接口的多继承

在Java中,类的多继承是不合法,但接口允许多继承,。

在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示:

public interface Hockey extends Sports, Event

10 标记接口

最常用的继承接口是没有包含任何方法的接口。

标识接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。

标识接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。

例如:java.awt.event 包中的 MouseListener 接口继承的 java.util.EventListener 接口定义如下:

package java.util;

public interface EventListener

{}

没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:

建立一个公共的父接口:

正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。

向一个类添加数据类型:

这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。

Java包

为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。

1 包的作用

1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。

2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。

3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

2 import 关键字

为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。使用 "import" 语句可完成此功能。

在 java 源文件中 import 语句应位于 package 语句之后,所有类的定义之前,可以没有,也可以有多条,其语法格式为:

import package1[.package2…].(classname|*);

如果在一个包中,一个类想要使用本包中的另一个类,那么该包名可以省略。

Java数据结构

1 枚举Enumeration

枚举接口虽然它本身不属于数据结构,但它在其他数据结构的范畴里应用很广。枚举接口定义了一种从数据结构中取回连续数据的方式。

2 位集合

位集合(BitSit)类实现了一组可以单独设置和清除的位或标志。

该类在处理一组布尔值的时候非常有用,你只需要给每个值赋值一"位",然后对位进行适当的设置或清除,就可以对布尔值进行操作了。

3 向量(Vector)

向量(Vector)类和传统数组非常相似,但是Vector的大小能根据需要动态的变化。

和数组一样,Vector对象的元素也能通过索引访问。

使用Vector类最主要的好处就是在创建对象的时候不必给对象指定大小,它的大小会根据需要动态的变化。

4 栈(Stack)

栈(Stack)实现了一个后进先出(LIFO)的数据结构。

你可以把栈理解为对象的垂直分布的栈,当你添加一个新元素时,就将新元素放在其他元素的顶部。

当你从栈中取元素的时候,就从栈顶取一个元素。换句话说,最后进栈的元素最先被取出。

5 字典(Dictionary)

字典(Dictionary) 类是一个抽象类,它定义了键映射到值的数据结构。

当你想要通过特定的键而不是整数索引来访问数据的时候,这时候应该使用Dictionary。

由于Dictionary类是抽象类,所以它只提供了键映射到值的数据结构,而没有提供特定的实现。

6 哈希表(Hashtable)

Hashtable类提供了一种在用户定义键结构的基础上来组织数据的手段。

例如,在地址列表的哈希表中,你可以根据邮政编码作为键来存储和排序数据,而不是通过人名。

哈希表键的具体含义完全取决于哈希表的使用情景和它包含的数据。

7 属性(Properties)

Properties 继承于 Hashtable.Properties 类表示了一个持久的属性集.属性列表中每个键及其对应值都是一个字符串。

Properties 类被许多Java类使用。例如,在获取环境变量时它就作为System.getProperties()方法的返回值。

Java集合框架

集合框架被设计成要满足一下目标

  • 该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的
  • 框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
  • 对一个集合的扩展和适应必须是简单的

集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:

接口:是代表集合的抽象数据类型。接口允许集合独立操纵其代表的细节。在面向对象的语言,接口通常形成一个层次。

实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构。

算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

1 Set和List的区别

1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。

2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。

3. List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。

2 Java泛型

泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

3 泛型方法

你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。

下面是定义泛型方法的规则:

①所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的<E>)。

②每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。

  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。

4 泛型类

泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。

和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。

5 方法重载与方法覆盖区别

方法重载(Overloading):如果有两个方法的方法名相同,但参数不一致,哪么可以说一个方法是另一个方法的重载。

方法覆盖(Overriding):如果在子类中定义一个方法,其名称、返回类型及参数签名正好与父类中某个方法的名称、返回类型及参数签名相匹配,那么可以说,子类的方法覆盖了父类的方法。

Java高级教程

Java  instanceof 关键字用法

instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。

instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。

以下实例创建了 displayObjectClass() 方法来演示 Java instanceof 关键字用法:

import java.util.ArrayList;

import java.util.Vector;

 

public class Main {

 

public static void main(String[] args) {

   Object testObject = new ArrayList();

      displayObjectClass(testObject);

   }

   public static void displayObjectClass(Object o) {

      if (o instanceof Vector)

      System.out.println("对象是 java.util.Vector 类的实例");

      else if (o instanceof ArrayList)

      System.out.println("对象是 java.util.ArrayList 类的实例");

      else

      System.out.println("对象是 " + o.getClass() + " 类的实例");

   }

}

2Java序列化

Java提供一种对象序列化机制,该机之中,一个对象可以被表示为一个自己序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中的数据类型。

将序列化对象写入文件后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据、还有对象中的数据类型都可以用来在内存中新建对象。

整个过程都是Java虚拟机JVM独立的。也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。

3 transient使用小结

  1. 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
  2. transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义的变量,则该类需要实现Serializable接口
  3. 被transient关键字修饰的变量不能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

3 FileInputStream

new一个FileInputStream时,使用绝对路径时要注意路径的分隔符可以用“/”或者“\\”,而这也可以混用,如下:

FileInputStream fis=new FileInputStream("D:/images/"+id+".jpg");

或者

FileInputStream fis=new FileInputStream("D:\\images\\"+id+".jpg");

4 java多线程编程

Java给多线程编程提供了内置的支持,一个多线程包含两个或多个能并发运行的部分。程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径。

多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。

进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守候线程都结束运行后才都结束。

多线程能满足程序员编写高效率的程序来达到充分利用CPU的目的。

5 线程状态

1)新建状态:

使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

2)就绪状态:

当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

3)运行状态:

如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

4)阻塞状态:

如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。

同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。

其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。

5)死亡状态:

一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

6 接口

好像定义接口是提前做了个多余的工作。下面我给大家总结了4点关于JAVA中接口存在的意义:

 

1、重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。

 

2、简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。

 

3、维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类。

可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦。

如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。

 

4、安全、严密性:接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。

7 线程的几个概念

在多线程编程时,你需要了解以下几个概念:

线程同步

线程间通信

线程死锁

线程控制:挂起、停止和恢复

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值