将客观事物看作具有状态和行为的对象,通过抽象找出同一类对象的共同状态和行为,构成类。
先通过编译器(Javac)编译为 .class文件,再由解释器(Java)从 .class文件中读一行解释一行
基本数据类型:数字型、字符型、布尔型
引用数据类型:类、接口、数组
第一个字符必须是大写字母、小写字母、_或$,后面的字符可以是字母,下划线,$或数字
数字不能作为标识符第一个字母
不能含有非法字符
关键字不能作为标识符
与C语言基本相同,在常量前加final关键字
//几种文字量类型
System.out.println(100);
System.out.println(3.14);
System.out.println(true);
System.out.println(false);
System.out.println('a');
System.out.println('中');
System.out.println("abc");
// System.out.println('ab'); 会编译报错,因为ab为字符串型要用双引号
System.out.println("国");// 这不属于字符型,因为使用双引号括起来了,所以是字符串型
扩展转换
byte, char, short, int, long, float, double:整数向float或double转换时会损失精度
窄化转化
double, float, long, int, short, byte,char:可能会丢失信息
转换方法(Java是强类型语言,赋值操作时对类型检查):赋值转化(将表达式类型转换为指定变量的类型,只能扩展转换)、方法调用转换、强制转换、字符串转化(任何类型都可以转换为字符串类型)
表达式是由一系列变量、运算符、方法调用构成
标准输入流:System.in
标准输出流:System.out
数组由同一类型的一连串对象或基本数据组成,并封装在同一个标识符。
数组是对象,数组名是一个引用。
在数组中可以调用Object类的所有方法
数组声明:Type[] arrayName;
、Type arrayName[]
int[] intArray;
String[] stringArray;
int intArray[]
String stringArray[]
数组的创建:arrayName = new Type[componets number];
int [] ai;
ai = new int[10];//元素个数可以是常量也可以是变量
int ai[] = new int[10];
数组初始化:如果在声明时给出了数组的初始值,则程序将利用初始值创建数组并进行初始化;如果没有指定初始值则默认为0,false,null
数组的引用:arrayName[index]
index类型为int short byte char
元素的个数:arrayName.length;下标最大值 length-1(从0开始计数),当下标超过最大值会产生ArrayIndexOutOfBoundsException
多维数组:可以为整个数组分配对象、也可以为每一行单独分配内存(当每行的元素个数不同时),数组中每行的个数可以不同
将属性及行为相同或相似的对象归为一类,可以看做是对象的抽象
类VS对象:对象是类的具体实例。类是构造对象的模板,对象在Stack中存储,类在Heap中创建
[public][abstract | final] class classname [extends father_class] [implements interfaces_name]{
//变量成员声明及初始化
//方法声明及方法体
}
注:每个编译单元(文件)只能有一个public类。即每个编译单元只能有一个公开的接口。public类的名字必须和这个编译单元的文件名完全相同。
Clock aclock; //对象的声明,并没有对象生成
aclock = new Clock();//在内存中为此对象分配内存空间
//aclock变量存储对象的引用,相当于对象的存储地址
[public| protected| private]//访问控制符
[static]//静态成员变量
[final]//常量的值不能被改变
[transient]//变量是临时状态
[volatile] //变量是一个共享变量
数据类型 变量名1[=value1];
//类变量实例
public class Point
{
private int x;
private int y;
public static int pointCount=0;
public Point(int x, int y){
this.x = x;
this.y = y;
pointCount++;
}
public static void main(String[] args)
{
Point p = new Point(1,1);
System.out.println(p.pointCount);// 1
Point q = new Point(2,2);
System.out.println(q.pointCount);// 2
System.out.println(q.pointCount == Point.pointCount);// true
System.out.println(Point.pointCount);// 2
}
}
[public | protected | private]
[static][final][abstract][native][synchronized] 返回类型 function_name(argv[0] value0,[argv[1] value1...]) [throw exception1,exception2...]{
方法体
}
实例方法:表示特定对象的行为,声明时前面不加static修饰符,需要在一个类实例上调用
public class Circle {
static double PI = 3.14159265;
int radius;
public double circumference() {
return 2 * PI * radius;
}
}
类方法:静态方法,表示类中对象共有的行为,需要加static修饰符,可以在不建立对象的情况下利用类名直接调用
不能使用this/super,使用时可用ClassName.var/ClassName.method()调用
不能被重写(但可以被隐藏(即除方法体其他均相同))
在静态方法中只能直接调用静态变量,静态方法或对象的属性和方法,不能直接使用非静态方法和非静态变量
public class Converter {
public static int centigradeToFahrenheit(int cent)
{
return (cent * 9 / 5 + 32);
}
}
//方法调用
Converter.centigradeToFahrenheit(40)
public class Circle {
static double PI = 3.14159265;
private int radius;
public double circumference() {
return 2 * PI * radius;
}
public int getRadius(){
return radius;
}
public void setRadius(int r){
radius = r;
}
}
public class CircumferenceTester {
public static void main(String args[]) {
Circle c1 = new Circle();
// c1.radius = 50; 编译器会报错,无法修改
c1.setRadius(50);
Circle c2 = new Circle();
// c2.radius = 10; 编译器会报错,私有变量无法从外部类直接修改
c2.setRadius(10); //正确方法
double circum1 = c1.circumference();
double circum2 = c2.circumference();
System.out.println("Circle 1 has circumference " + circum1);
System.out.println("Circle 2 has circumference " + circum2);
}
}
public BankAccount() {
this("", 999999, 0.0f);
}
public BankAccount(String initName, int initAccountNumber) {
this(initName, initAccountNumber, 0.0f);
}
public BankAccount(String initName, int initAccountNumber,
float initBalance) {
ownerName = initName;
accountNumber = initAccountNumber;
balance = initBalance;
}
public void saveMoney(double balance){
this.balance = balance;
}
语法:
class childClass extends parentClass{
类体
}
public class Person {
public String name;
public String getName() {
return name;
}
}
public class Employee extends Person {
public int employeeNumber;
public int getEmployeeNumber() {
return employeeNumber;
}
}
public class Manager extends Employee {
public String responsibilities;
public String getResponsibilities() {
return responsibilities;
}
}
子类不能直接访问从父类中继承的私有属性及方法,但可使用公有(及保护)方法进行访问
public class B {
public int a = 10;
private int b = 20;
protected int c = 30;
public int getB() { return b; }
}
public class A extends B {
public int d;
public void tryVariables() {
System.out.println(a); //允许
System.out.println(b); //不允许
System.out.println(getB()); //允许
System.out.println(c); //允许
}
}
被final修饰符修饰的类和方法
终结类不能被继承
终结方法不能被当前类的子类重写
不能被实例化,必须有子类覆盖其声明的方法
Java基础类库:java.lang、java.util、java.io
本质是参数化类型,所有类型转换都是自动和隐式的
泛型类:在类名后面加上
泛型方法:在方法名前加上
class GeneralType <Type> {
Type object;
public GeneralType(Type object) {
this.object = object;
}
public Type getObj() {
return object;
}
}
public class Test {
public static void main(String args[]){
GeneralType<Integer> i = new GeneralType<Integer> (2);
GeneralType<Double> d = new GeneralType<Double> (0.33);
System.out.println("i.object=" + (Integer)i.getObj());
// System.out.println("i.object=" + (Integer)d.getObj()); 不能通过编译
}
}
class GeneralType <Type> {
Type object;
public GeneralType(Type object) {
this.object = object;
}
public Type getObj() {
return object;
}
}
class ShowType {
public void showType(GeneralType<?> o) {//"?"表示通配符,可以传入任意类型的数据
System.out.println(o.getObj().getClass().getName());
}
}
public class Test {
public static void main(String args[]){
ShowType st = new ShowType();
GeneralType<Integer> i = new GeneralType<Integer> (2);
GeneralType<String> s = new GeneralType<String> ("hello");
st.showType(i);
st.showType(s);
}
}
//程序的运行结果如下:
//java.lang.Integer
//java.lang.String
class GeneralType <Type extends Number> {
Type object;
public GeneralType(Type object) {
this.object = object;
}
public Type getObj() {
return object;
}
}
public class Test {
public static void main(String args[]){
GeneralType<Integer> i = new GeneralType<Integer> (2);
//GeneralType s = new GeneralType ("hello");//非法,
//T只能是Number或Number的子类
}
}
是一个纯抽象类,允许创建者规定方法的基本形式:方法名、参数列表以及返回类型,但不规定方法主体,也可以包含基本数据类型的数据成员,但都默认为static和final
为了实现多继承
注:接口数据成员为static/final,方法成员为abstract
接口作用:允许我们在看起来不相干的对象之间定义共同行为
//接口定义
interface 接口名称 [extends 父接口名]{
/*方法的原型声明或静态常量,数据成员一定要赋值,可以忽略public和abstract关键字*/
}
public interface Insurable {
public int getNumber();
public int getCoverageAmount();
public double calculatePremium();
public Date getExpiryDate();
}
//接口实现
public class 类名称 implements 接口名称{
/* Bodies for the interface methods */ /* Own data and methods. */
}
//必须实现接口中所有方法,来自接口的方法必须声明成public
//被塑性成更一般的类
Employee emp;
emp = new Manager();//将Manager类型的对象直接赋给Employee类的引用变量,将Manager对象塑性为Employee类
//被塑性为对象所属类实现的接口类型
Car jetta = new Car();
Insurable item = jetta;
//基本数据类型
(int)871.34354; //871
(char)65;//'A'
(long)453; // 453L
//引用变量:还原为本来的类型
Employee emp;
Manager man;
emp = new Manager();//将Manager向上塑型为Employee,此时emp中如果有被重写的方法,则调用Manager类中的方法,但此时不能调用Manager类中的特有方法
man = (Manager)emp;//将Manager还原回去,此时可以调用Manager类中的特有方法
//在向上和向下的塑型过程中一直只有一个Manager被转换,不能转换为Employee的其他子类,只能向下塑型回Manager类
应用场合
方法的查找
public class BindingTester{
public static void main(String[] args) {
Shape[] s = new Shape[9]; //Shape为Circle、Square、Triangle的基类
int n;
for(int i = 0; i < s.length; i++) {
n = (int)(Math.random() * 3);
switch(n) {
case 0:
s[i] = new Circle();
break;
case 1:
s[i] = new Square();
break;
case 2:
s[i] = new Triangle();
}
}
for(int i = 0; i < s.length; i++) s[i].draw();
}
}//编译时无法知道s数组元素的具体类型,运行时才能确定类型,所以是动态绑定
数组元素都是类的对象、所有元素具有相同的类型、每个元素都是一个对象的引用
//在声明和定义数组的同时对数组元素进行初始化
BankAccount[] accounts = {
new BankAccount(“Zhang", 100.00),
new BankAccount(“Li", 2380.00),
new BankAccount(“Wang", 500.00),
new BankAccount(“Liu", 175.56),
new BankAccount(“Ma", 924.02)};
//先定义再初始化
//首先给数组分配空间
type arrayName[] = new type[arraySize];
//然后给每一个数组元素分配空间
arrayName[0] = new type(paramList);
...
arrayName[arraySize-1] = new type(paramList);
元素有顺序,每个元素都有对应的index值,元素可以重复
非同步的
相同 | 不同 |
---|---|
都可以表示一组同类型的对象 | 数组可以存任何类型元素,List不可以存基本数据类型 |
都使用下标进行索引 | 数组容量固定,List容量可变 |
数组效率高,List效率低一些 |
push入栈
pop栈顶元素出栈,并返回
peek获取栈顶元素
禁止重复元素,HashSet,其中哈希函数为hashCode
声明了一组操作成批对象的抽象方法:查询方法、修改方法
查询方法
int size() – 返回集合对象中包含的元素个数
boolean isEmpty() – 判断集合对象中是否还包含元素,如果没有任何元素,则返回true
boolean contains(Object obj) – 判断对象是否在集合中
boolean containsAll(Collection c) – 判断方法的接收者对象是否包含集合中的所有元素
修改方法包括
boolean add(Object obj) – 向集合中增加对象
boolean addAll(Collection> c) – 将参数集合中的所有元素增加到接收者集合中
boolean remove(Object obj) –从集合中删除对象
boolean removeAll(Collection c) -将参数集合中的所有元素从接收者集合中删除
boolean retainAll(Collection c) – 在接收者集合中保留参数集合中的所有元素,其它元素都删除
void clear() – 删除集合中的所有元素
不是Collection接口的继承
存在键值对,不能有重复关键字,每个关键字映射一个值
HashMap速度很快,但没有顺序
hasNext():判断是否还有元素
next():取得下一个元素
remove():去除一个元素,是从集合中去除最后调用next()返回的元素,而不是从Iterator类中去除
import java.util.Vector;
import java.util.Iterator;
public class IteratorTester {
public static void main(String args[]) {
String[] num = {"one", "two", "three", "four", "five",
"six", "seven", "eight", "nine", "ten"};
Vector<String> aVector = new Vector<String> (java.util.Arrays.asList(num));
System.out.println("Before Vector: " + aVector);
Iterator<String> nums = aVector.iterator();
while(nums.hasNext()) {
String aString = (String)nums.next();
System.out.println(aString);
if (aString.length() > 4) nums.remove();
}
System.out.println("After Vector: " + aVector);
}
}
在Java中将信息的输入与输出过程抽象为I/O流
从流的处理来分
- 节点流:从数据源读入或往目的地写出数据
- 处理流:对数据执行某种处理(不直接与数据源或目标相连,而是基于另一个流来构造)
//输入单个字符
import java.util.Scanner;
public class Demo59 {
public static void main(String[] args) {
//创建Scanner对象,接受从控制台输入
Scanner input=new Scanner(System.in);//默认为键盘;System.in 程序启动时自动创建的流对象,是原始的字节流
// setIn(InputStream);设置标准输入流
// setOut(PrintStream); 设置标准输出流
//接受String类型
String str=input.next();
//输出结果
System.out.println(str);//默认为屏幕输出
}
//输入一串字符
import java.util.Scanner;
public class Demo59 {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
//输入数组的长度
int len=input.nextInt();//根据返回类型不同,进行更改,nextByte(),nextDouble(),nextFloat,nextInt(),nextLine(),nextLong(),nextShort()
//创建一个数组
int[] array=new int[len];
//遍历数组,并给其赋值
for(int i=0;i<len;i++){
array[i]=input.nextInt();
}
//打印数组
for(int i:array){
System.out.print(i+" ");
}
}
}
//持续输入并随之回车输出
import java.io.*;
public class Echo {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//BufferedReader 对InputStreamReader处理后的信息进行缓冲,InputStreamReader属于处理流
String s;
while((s = in.readLine()).length() != 0)
System.out.println(s);
}
}
常用类:FileWriter(节点流)、BufferedWriter、OutputStreamWriter
//写入文件中
import java.io.*;
class FileWriterTester {
public static void main ( String[] args ) throws IOException {
//main方法中声明抛出IO异常
String fileName = "C:\\Hello.txt";
//每次运行都将删除原有的文件,创建同名文件,重新写入
FileWriter writer = new FileWriter( fileName ); //一共有五种构造方法
//FileWriter writer = new FileWriter( fileName ,true );
//运行此句程序,会发现在原文件内容后面又追加了重复的内容,这就是将构造方法的第二个参数设为true的效果
writer.write( "Hello!\n");
writer.write( "This is my first text file,\n" );
writer.write( "You can see how this is done.\n" );
writer.write("输入一行中文也可以\n");
writer.close();
}
}
当需要写入的内容很多时,利用更高效的缓冲器流类BufferedWriter
import java.io.*;
class BufferedWriterTester {
public static void main ( String[] args ) throws IOException {
String fileName = "C:/newHello.txt" ;
BufferedWriter out = new BufferedWriter( new FileWriter( fileName ) );
out.write( "Hello!" );
out.newLine() ; //换行
out.write( "This is another text file using BufferedWriter," );
out.newLine(); ;
out.write( "So I can use a common way to start a newline" );
out.close();
}
}
常用类:FileReader(节点流)、BufferedReader、InputStreamReader
继承自Reader抽象类的子类InputStreamReader,从文本文件中读取字符
读文本文件的缓冲器类,继承自Reader
//文件读入
import java.io.*;
class BufferedReaderTester {
public static void main ( String[] args ) {
String fileName = "C:/Hello.txt" , line;
try {
BufferedReader in = new BufferedReader(new FileReader( fileName ) );//若文件不存在会抛出IOException
line = in.readLine(); //读取一行内容
while ( line != null ) {
System.out.println( line );
line = in.readLine();
}
in.close(); //一定要记得关闭文件
//int c;
//while((c=in.read())!= -1) System.out.print((char)c);
//Reader类的read()方法也可用来判别文件结束。该方法返回的一个表示某个字符的int型整数,如果读到文件末尾,返回 -1
}
catch ( IOException iox ) {
System.out.println("Problem reading " + fileName );
}
}
}
常用类:FileOutputStream、BufferedOutputStream、DataOutputStream
import java.io.*;
class FileOutputstreamTester {
public static void main ( String[] args ) {
String fileName = "c:/data1.dat" ;
int value0 = 255, value1 = 0, value2 = -1;
try {
DataOutputStream out = new DataOutputStream(new FileOutputStream( fileName ) );
out.writeInt( value0 );
out.writeInt( value1 );
out.writeInt( value2 );
out.close();
}
catch ( IOException iox ){
System.out.println("Problem writing " + fileName ); }
}
}
//写完后查看二进制信息,发现内容为00 00 00 FF 00 00 00 00 FF FF FF FF
类似于BufferedWriter,对于大量数据的写入可以提高效率
//向文件中写入各种数据类型的数,并统计写入的字节数
import java.io.*;
class BufferedOutputStreamTester {
public static void main ( String[] args ) throws IOException {
String fileName = "mixedTypes.dat" ;
DataOutputStream dataOut = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream( fileName ) ) );
dataOut.writeInt( 0 );
System.out.println( dataOut.size() + " bytes have been written.");//4
dataOut.writeDouble( 31.2 );
System.out.println( dataOut.size() + " bytes have been written.");//12
dataOut.writeBytes("JAVA");
System.out.println( dataOut.size() + " bytes have been written.");//16
dataOut.close();
}
}
常用类:FileInputStream、DataInputStream、BufferedInputStream
import java.io.*;
class DataInputStreamTester {
public static void main ( String[] args ) {
String fileName = "c:/data1.dat" ; long sum = 0;
try {
DataInputStream instr = new DataInputStream(
new BufferedInputStream(new FileInputStream(fileName)));
try {
while ( true )
sum += instr.readInt();
}
catch ( EOFException eof ) {//遇到文件结尾会抛出此异常
System.out.println( "The sum is: " + sum );
instr.close();
}
}
catch ( IOException iox ) {
System.out.println("IO Problems with " + fileName ); }
}
}
}
//文本文件的存储方式也是二进制代码,也可以用InputStream类的方法读取
import java.io.*;
public class InputStreamTester {
public static void main(String[] args) throws IOException {
FileInputStream s=new FileInputStream("c:/Hello.txt");
int c;
while ((c = s.read()) != -1) //读取1字节,结束返回-1
System.out.write(c);
s.close();
}
}
在Error类下的错误都是用户程序无法解决的
public void openThisFile(String filename) throws FileNotFoundException{
}
//也可以同时抛出多个异常
public void openThisFile(String filename) throws FileNotFoundException,ClassNotFoundException{
}
//可以通过手动显式抛出一个异常(throw)
public void setRadius(double newRadius) throws IllegalArgumentException {
if (newRadius >= 0)
radius = newRadius;
else
throw new IllegalArgumentException("Radius cannot be negative");
}
//可以同时catch多个异常
try{
statements;
}
catch(Exception1 exVar1){
handler for exception1;//可用throw语句生产异常对象
// throw new Exception(); 重复抛出异常
}
catch(Exception2 exVar2){
handler for exception2;
}
//finally用法
//some codes
try {
statements;
}
catch(TheException ex) {
handling ex;
}
finally {
finalStatements;
}
Next Statements;
要extends Exception
同时在构造函数里面要super("");
一个程序中多段代码同时并发执行
实现了Runnable接口,位于java.lang包中
public class FactorialThreadTester{
public static void main( String [] args) {
System.out.println("main thread starts");
FactorialThreadthread=new FactorialThread(10);
thread.start(); //将自动进入run()方法System.out.println("main thread ends " );
}
}
class FactorialThread extends Thread{
private int num;
public FactorialThread( int num ) {
this.num=num;
}
public void run() {
int i=num;
ntresult=1;
System.out.println("new thread started" );
while(i>0) {
result=result*i;
i=i-1;
}
System.out.println("The factorial of "+num+" is "+result);
System.out.println("new thread ends");
}
}
//运行结果
//main thread starts 说明main函数启动后没有等待run()返回完成,就继续运行
//main thread ends
//new thread started
//The factorial of 10 is 3628800
//new thread ends
在启动多个线程的时候,程序启动线程的顺序是随机的
//共用一个数据
public class TestThread implements Runnable{
private int sleepTime;
public TestThread() {
sleepTime= (int)(Math.random()*6000);
}
public void run() {
try {
System.out.println(Thread.currentThread().getName()+" going to sleep for "+sleepTime);
Thread.sleep(sleepTime);
}catch(InterruptedException exception) {};
System.out.println(Thread.currentThread().getName()+" finished");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
TestThread thread1 = new TestThread();
System.out.println("Starting threads");
//使用Runnable接口的类要用Thread(Runnable target[,name]),方法创建对象
new Thread(thread1,"Thread1").start();
new Thread(thread1,"Thread2").start();
new Thread(thread1,"Thread3").start();
System.out.println("Threads strat,main ends\n");
}
}
// 运行结果
//Starting threads
//Threads strat,main ends
//Thread1 going to sleep for 4506
//Thread2 going to sleep for 4506
//Thread3 going to sleep for 4506
//Thread3 finished
//Thread1 finished
//Thread2 finished
线程同步:
- 互斥:许多线程在同一个共享数据上操作而互不干扰,同一时刻只能有一个线程访问该共享数据,有些方法或程序段在同一时刻只能被一个线程执行,称之为监视区
实现互斥,用于指点需要同步的代码段或方法
功能:判断这个对象可以不可以被使用(锁旗标在不在),如果可以(锁旗标在)就执行后面的代码段(拿走锁旗标);如果不能被使用(锁旗标不在,此数据被其他线程使用),就进入等待状态,直到可以使用此对象。用完后释放锁旗标
//将需要互斥的语句段放入synchronized(object){}语句中,且两处的object是相同的
class Producer extends Thread {
Tickets t=null;
public Producer(Tickets t) {
this.t=t;
}
public void run() {
while((t.number)<t.size) {
synchronized(t){ // 申请对象t的锁旗标
System.out.println("Producer puts ticket" +(++t.number));
t.available=true;
} // 释放对象t的锁旗标
}
System.out.println("Producer ends!");
}
}
class Consumer extends Thread {
Tickets t=null;
int i=0;
public Consumer(Tickets t) {
this.t=t;
}
public void run() {
while(i<t.size) {
synchronized(t) { //申请对象t的锁旗标
if(t.available==true && i<=t.number)
System.out.println("Consumer buys ticket "+(++i));
if(i==t.number) {
try{
Thread.sleep(1);
} catch(Exception e){}
t.available=false;
}
}//释放对象t的锁旗标
}
System.out.println("Consumer ends");
}
}
除了对指定的代码段进行同步控制,还可以定义整个方法在同步控制下进行
class Tickets {
int size; //票总数
int number=0; //存票序号
int i=0; //售票序号
boolean available=false; //是否有待售的票
public Tickets(int size) {
this.size=size;
}
public synchronized void put(){ //同步方法,实现存票的功能
System.out.println("Producer puts ticket "+(++number));
available=true;
}
public synchronized void sell(){ //同步方法,实现售票的功能
if(available==true && i<=number)
System.out.println("Consumer buys ticket "+(++i));
if(i==number) available=false;
}
}
class Producer extends Thread{
Tickets t=null;
public Producer(Tickets t) {
this.t=t;
}
public void run(){//如果存票数小于限定总量,则不断存入票
while(t.number<t.size) t.put();
}
}
class Consumer extends Thread{
Tickets t=null;
public Consumer(Tickets t){
this.t=t;
}
public void run(){//如果售票数小于限定总量,则不断售票
while(t.i<t.size) t.sell();
}
}
线程的几种状态:
诞生状态、就绪状态(start方法已被执行)、运行状态、阻塞状态(发出请求且必须等待其返回,遇到synchronized但不能使用时)、休眠状态(sleep方法)、死亡状态(线程已完成或退出)