Java笔记

Java

基础知识

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

JAVA特点

对象

一个可表示的存储区域

  • 属性:变量
  • 行为:函数
class Person
{
    int age;
	String name;
	void sayHello()
}	

对象

Person p = new Person()

模块化

将属性和行为封装在类中,程序定义很多类

class Person
{
private int age;
public int getAge(){return age;}
public void setAge(int a){age=a;}
void sayHello(){}
}

继承性

  • 父类和子类之间共享数据和方法

  • 父类

    class person
    {
    	int age;
    	String name;
    	void sayHello(){}
    }
    
  • 子类

    class Student extends Person
    {
    	String school;
    	double score;
    	void meetTeacher(){}
    }
    

    子类便继承了父类的那些功能属性,并且具有子类这些更新的属性

  • 好处:

    1. 更好的进行抽象与分类
    2. 增加代码的重用率
    3. 提高维护性

多态

不同的对象收到一个调用方法可产生完全不同的效果
老师和学生虽然都被一个函数调用却能产生两种不同的打招呼方式

foo(Person p) {p.sayHello();}
foo(new Student());
foo(new Teacher());

程序的分析和设计都围绕

  1. 有哪些对象
  2. 每个类有哪些属性,方法
  3. 类之间的关系(继承,关联)
  4. 对象之间调用方法

JAVA SE类型:Application和Applet程序

  • 结构和运行环境不同
  • 前者是独立的程序,需要执行器(调用虚拟机)来运行
  • 后者是嵌在HTML网页中的非独立的程序
    由专门的appletViewer来运行或者由Web浏览器(调用JAVA虚拟机)来运行

普通的应用程序

class是主体
public类名与文件同名
main()写法固定
System.out.print 及println及printf

public class HelloWorldApp
{
	public static void main(String args[])
	{
		System.out.println(Hello World!);
	}
}       

Applet程序

import表示导入
extends JApplet表示继承 Applet或JApplet都可以
有paint()方法,表示如何绘制
没有main()方法

import java.awt.*;
import java.applet.*;
import javax.swing.*;
public class HelloWorldApplet extends JApplet
{
	public void paint(Graphics g)
	{
		g.drawString(Hello World!,20,20);
	}
}
//这个.java不能单独运行
//要配合html使用
<HTML>
<HEAD><TITLE> An Applet</TITLE></HEAD>
<BODY>
<applet code=HelloWorldApplet.class"
	width=200 height=40 background=white>
</applet>
</BODY>
</HTML>

JAVA程序的基本构成

  • package语句(0或1句) package edu.pku.tds.ch02;
  • import语句(0或多句) import java.util.*;导入其它类的类库
  • 类定义—class(1或多个) public class HelloDate {
    一个文件只能有一个public类(与文件同名)
    类=类头+类体
    类成员=字段(field)+方法(method)
    字段(field,属性,变量)
    方法(method,函数)
    方法=方法头+方法体

JDK安装后的文件夹

  • bin 存放工具文件
  • jre存放与java运行环境相关的文件
  • demo存放一些示例文件
  • include 存放与C相关的头文件
  • lib存放程序库
  • db数据库相关

Application编辑编译运行

程序编译

转换为字节码(bytecode)文件,扩展名.class
(.class文件中包含java虚拟机的指令)
编译使用JDK工具javac.exe
javac Hello.java

程序运行

执行.class文件中的指令的过程
java Hello
不能写成java Hello.class

Applet编辑编译运行

在HTML中嵌入Applet
使用标签
<applet code= “HelloWorldApplet.class" width=200 height=40 background=white> appletViewer HelloWorldApplet.html

工具

主要工具

javac 编译
java 运行(控制台及图形界面程序)
javaw运行图形界面程序
appletViewer运行apple程序

常用的工具

jar 打包工具
javadoc生成文档
javap 查看类信息及反汇编

使用jar打包

编译javac A.java
打包jar cvfm A.jar A.man A.class
c表示create,v表示显示详情verbose,f表示指定文件名,m表示清单文件
运行java-jar A.jar

其中A.man是清单文件(manifest),内容如下:
manifest-Version:1.0
Class-Path:.
Main-Class:A
清单文件可以任意命名,常见的使用MANIFEST.MF

使用JavaDoc生成文档

Javadoc -d目录名xxx.java
/** */这其中可以用一下标记
@auther对类说明 标记开发该类模块的作者
@version对类的说明 标明该类模块的版本
@see 对类,属性,方法的说明 参考转向,也就是相关主题
@param 对方法的说明 对方法中某参数的说明
@return 对方法的说明 对方法返回值的说明
@exception 对方法的说明 对方法可能抛出的异常进行说明

使用javap
  • 使用javap查看类的信息:
    javap 类名
  • 使用javap反汇编:
    javap -c 类名

输入输出

文本界面

使用java.util.Scanner类
import java.util.Scanner;
class ScannerTest
{
	public static void main(String[] args)
	{
		Scanner scanner = new Scanner(System.in);
		System.out.print(“请输入一个数”);
		int a = scanner.nextInt();
		System.out.printf(%d的平方是%d\n”,a,a*a);
	}
}
使用java.io包

System.in.read()
System.out.print()及println,printf 类似于C语言

AppCharInOunt.java得到一个字符
char c = ‘ ’;
System.out.print(PPlease input a char:)
try
{
	c = (char) System.in.read();
}
catch(IOException e){}
System.out.println(You have entered:+ c);
AppLineInOut.java输入输出行
try
{
	BufferedReader in = new BufferedReader(
        new InputStreamReader(System.in();
	s = in.readLine();
}
catch(IOExeption e){}
AppNumInout.java输入输出数字
BufferedReader in = new BufferedReader(
	new InputStreamReader(System.in));
System.out.print(Please input an int:);
s = in.readLine();
n = Integer.parseInt(s);
//如果是double类型则为Double.parseDouble(s)

图形界面下

使用文本框对象TextField获取输入数据
使用标签对象Label或文本框对象输出数据
使用命令按钮Button来执行命令

Java Application要创建自己的图形界面

通过Frame创建自己的用户界面,在构建AppFrame时,设定该Frame大小,并用setVisible(true)方法显示出来

  • add(xxxx)加入对象
  • btn.addActionListener处理事件
  • actionPerformed()函数 具体处理事件
setLayout(new FlowLayout());
add(in);
add(btn);
add(out);
btn.addActionListener(new BtnActionAdapter());	
class BtnActionAdapter implements ActionListener
{
	public void actionPerformed(ActionEvent e)
	{
		String s = in.getText();
		double d = Double.parseDouble(s);
		double sq = Math.sqrt(d);
		out.setText( d + “的平方根是:+ sq);
	}
}
//Java8后可简化为:
btn.addAcitonListener(e->{
	String s = in.getText();
	double d = Double.parseDouble(s);
	double sq = Math.sqrt(d);
	out.setText( d + “的平方根是:+ sq);
});
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class AppGraphInOut {
    public static void main(String args[]) {
        new AppFrame();//在main里面构建一个Frame对象
    }
}

class AppFrame extends JFrame {
    JTextField in = new JTextField(10);
    JButton btn = new JButton("求平方");
    JLabel out = new JLabel("用于显示结果的标签");

    public AppFrame() {
        setLayout(new FlowLayout());
        getContentPane().add(in);//流式内容
        getContentPane().add(btn);
        getContentPane().add(out);
        btn.addActionListener(new BtnActionAdapter());
        setSize(400, 100);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setVisible(true);
    }

    class BtnActionAdapter implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            String s = in.getText();
            double d = Double.parseDouble(s);
            double sq = d * d;
            out.setText(d + "的平方是:" + sq);
        }
    }
}
Applet输入输出

AppletInOut.java
在init()中:
add(xxx)加入对象
btn.addActionListener 处理事件
actionPerformed()函数 具体处理事件

import javax.swing.*;
import java.awt.*;

public class AppletInOut8 extends JApplet {
    JTextField in = new JTextField(10);
    JButton btn = new JButton("求平方根");
    JLabel out = new JLabel("用于显示结果的标签");

    public void init() {
        setLayout(new FlowLayout());
        add(in);
        add(btn);
        add(out);
        btn.addActionListener(e -> {
            String s = in.getText();
            double d = Double.parseDouble(s);
            double sq = Math.sqrt(d);
            out.setText(d + "的平方根是:" + sq);
        });
    }
}

同时作为Application和Applet的程序三个条件

  1. 是Applet的派生
  2. 含有main();
  3. 在main()中创建一个用户界面,并将这个Applet加入
import javax.swing.*;
import java.awt.*;

public class AppAppletInOut extends JApplet {
    public static void main(String args[]) {
        JFrame frame = new JFrame();
        AppAppletInOut app = new AppAppletInOut();
        app.init();
        frame.getContentPane().add(app);
        frame.setSize(400, 100);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//关闭窗口
        frame.setVisible(true);
    }

    JTextField in = new JTextField(10);
    JButton btn = new JButton("求平方根");
    JLabel out = new JLabel("用于显示结果的标签");

    public void init() {
        setLayout(new FlowLayout());
        add(in);
        add(btn);
        add(out);
        btn.addActionListener(e -> {
            String s = in.getText();
            double d = Double.parseDouble(s);
            double sq = Math.sqrt(d);
            out.setText(d + "的平方根是:" + sq);
        });
    }
}

数据类型

基本数据类型

变量在栈,赋值时复制的是值

  • 数值型

    • 整数类型:byte1,short2,int4,long8
    • 浮点类型:float4,double8 默认为double,或者float a=1.2f使其为float
  • 字符型:char

  • 布尔型:boolean

    public class BooleanTest {
        public static void main(String args[]) {
            boolean a = false;
            boolean b = true;
            System.out.println(a + " " + b);
        }
    }
    

引用数据类型

变量引用到堆,类似指针,赋值时复制的是引用

  • 类:class
  • 接口:interface
  • 数组

采用Unicode编码

每个字符占两个字节 char c = ‘\u0061’

进制

八进制:0开头,012
十六进制:0x或0X开头,0x12
二进制:0b或0B开头,0b00010010

无无符号数,unsigned int

类名首字母大写,其余小写

运算符

短路逻辑运算符

&& 第一个操作符为假则不判断第二个操作数
|| 第一个操作数为真则不判定第二个操作数

if((d != NULL) && (d.day > 31))
{
//则它只会先判断第一个是否成立,在第一个成立的前提下才去看第二个
}
public class LeapYear {
    public static void main(String args[]) {
        int year = 2003;
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
            System.out.println(year + " is a leap year.");
        }
        else {
            System.out.println(year + " is not a leap year.");
        }
    }
}

位运算

左移:a<<b;最低位空出的b位补0
带符号右移:a>>b;最高位空出的b位补原来的符号位
无符号右移:a>>>b;最高位空出的b位补0

public class BitwiseOperators {
    public static void main(String args[]) {
        int a = 0b1100;
        int b = 0b1010;
        print("a ", a);
        print("b ", b);
        print("a&b", a & b);
        print("a|b", a | b);
        print("a^b", a ^ b);
        print("~a", ~a);
        print("a<<2", a << 2);
        print("a>>2", a >> 2);
        print("a>>>2", a >>> 2);
    }

    static void print(String prefix, int n) {
        String s = Integer.toBinaryString(n);
        while (s.length() < 4) {//长度不够就补0
            s = "0" + s;
        }
        System.out.println(prefix + " " + s);
    }
}

+可以连接字符串

public class GradeLevel {
    public static void main(String args[]) {
        char grade = 'C';
        switch (grade) {
            case 'A':
                System.out.println(grade + " is 85~100");
                break;
            case 'B':
                System.out.println(grade + " is 70~84");
                break;
            case 'C':
                System.out.println(grade + " is 60~69");
                break;
            case 'D':
                System.out.println(grade + " is <60");
                break;
            default:
                System.out.println("Input Error");
        }
    }
}

break语句选择跳出哪一层循环

lable1:{
lable2:    {
lable3:        {
	               break label2;
	           }
	       }
	   }
//从里层循环直接跳出二至多层
public class Rnd_36_7
{
    public static void main(String args[])
    {
        int a[] = new int[7];
        for (int i = 0; i < a.length; i++)
        {
            one_num:
            while (true)
            {
                a[i] = (int) (Math.random() * 36) + 1;
                for (int j = 0; j < i; j++)
                {
                    if (a[i] == a[j])
                    {
                        continue one_num;
                    }
                    break;
                }
            }
        }
        for (int num : a)
        {
            System.out.println(num + " ");
        }
        System.out.println();
    }
}
public class Prime100Continue
{
    public static void main(String args[])
    {
        System.out.println("****100--200的质数****");
        int n = 0;
        outer:
        for (int i = 0; i < 200; i += 2)
        {//外层循环
            for (int j = 2; j < 2; j++)
            {//内层循环
                if (i % j == 0)
                {//不是质数,则继续外层循环
                    continue outer;
                }
            }
            System.out.println(" " + i);//显示质数
            n++;//计算个数
            if (n < 10)
            {//未满十个数不换行
                continue;
            }
            System.out.println();
            n = 0;
        }
        System.out.println();
    }
}
import javax.swing.*;
import java.awt.*;

public class AutoScore extends JFrame
{
    public static void main(String [] argv)
    {
        JFrame frame = new AutoScore();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600,600);
        frame.setVisible(true);
    }

    public AutoScore()
    {
        init();
        setSize(400, 350);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void init()
    {
        setLayout(null);//手动布局
        setSize(400, 350);
        btnNew.setLabel("出题");
        getContentPane().add(btnNew);
        btnNew.setBackground(java.awt.Color.lightGray);
        btnNew.setBounds(36, 96, 98, 26);
        btnJudge.setLabel("判分");
        getContentPane().add(btnJudge);
        btnJudge.setBackground(java.awt.Color.lightGray);
        btnJudge.setBounds(216, 96, 94, 25);

        lblA.setText("text");
        getContentPane().add(lblA);
        lblA.setFont(new Font("Dialog", Font.PLAIN, 24));
        lblA.setBounds(36, 24, 36, 36);

        lblOp.setText("text");
        getContentPane().add(lblOp);
        lblOp.setFont(new Font("Dialog", Font.PLAIN, 24));
        lblOp.setBounds(72, 24, 36, 36);

        lblB.setText("text");
        getContentPane().add(lblB);
        lblB.setFont(new Font("Dialog", Font.PLAIN, 24));
        lblB.setBounds(108, 24, 33, 36);

        label5.setText("=");
        getContentPane().add(label5);
        label5.setFont(new Font("Dialog", Font.PLAIN, 24));
        label5.setBounds(168, 24, 33, 36);

        getContentPane().add(txtAnswer);
        txtAnswer.setFont(new Font("Dialog", Font.PLAIN, 24));
        txtAnswer.setBounds(216, 24, 85, 42);

        listDisp.setFont(new Font("Dialog", Font.PLAIN, 24));
        getContentPane().add(listDisp);
        listDisp.setBounds(36, 144, 272, 106);

        SymAciton lSymAction = new SymAciton();
        btnNew.addActionListener(lSymAction);
        btnJudge.addActionListener(lSymAction);
    }

    java.awt.Button btnNew = new java.awt.Button();
    java.awt.Button btnJudge = new java.awt.Button();
    java.awt.Label lblA = new java.awt.Label();
    java.awt.Label lblOp = new java.awt.Label();
    java.awt.Label lblB = new java.awt.Label();
    java.awt.Label label5 = new java.awt.Label();
    java.awt.TextField txtAnswer = new java.awt.TextField();
    java.awt.List listDisp = new java.awt.List(0);

    class SymAciton implements java.awt.event.ActionListener
    {//接口

        public void actionPerformed(java.awt.event.ActionEvent event)
        {//方法
            Object object = event.getSource();
            if (object == btnNew)
            {
                btnNewActionPerformed(event);
            }
            else
            {
                btnJudgeActionPerformed(event);
            }
        }
    }

    void btnNewActionPerformed(java.awt.event.ActionEvent event)
    {
        a = (int) (Math.random() * 9 + 1);
        b = (int) (Math.random() * 9 + 1);
        int c = (int) (Math.random() * 4);
        switch (c)
        {
            case 0:
                op = "+";
                result = a + b;
                break;
            case 1:
                op = "-";
                result = a - b;
                break;
            case 2:
                op = "*";
                result = a * b;
                break;
            case 3:
                op = "/";
                result = a / b;
                break;
        }
        lblA.setText("" + a);
        lblB.setText("" + b);
        lblOp.setText("" + op);
        txtAnswer.setText("");
    }

    int a = 0, b = 0;
    String op = "";
    double result = 0;

    void btnJudgeActionPerformed(java.awt.event.ActionEvent event)
    {
        String str = txtAnswer.getText();
        double d = Double.valueOf(str).doubleValue();
        String disp = "" + a + op + b + "=" + str + "";
        if (d == result)
        {
            disp += "Yes";
        }
        else
        {
            disp += "No";
        }

        listDisp.add(disp);
    }
}
import javax.swing.*;
import java.awt.*;

public class Circle99Frame extends JFrame
{
    public static void main(String[] argv)
    {
        JFrame frame = new Circle99Frame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 600);
        frame.setVisible(true);
    }

    public void paint(Graphics g)
    {
        g.drawString("circle 90", 20, 20);

        int x0 = getSize().width / 2;
        int y0 = getSize().height / 2;

        for (int r = 0; r < getSize().height / 2; r += 10)
        {
            g.setColor(getRandomColor());
            g.drawOval(x0 - r, y0 - r, r * 2, r * 2);
        }
    }

    Color getRandomColor()
    {
        return new Color(
                (int) (Math.random() * 255),
                (int) (Math.random() * 255),
                (int) (Math.random() * 255)
        );
    }
}

数组

数组定义与为数组元素分配空间分开进行

int a[] = new int[3];//分配空间
a[0] = 3;
a[1] = 9;
a[2] = 8;
MyDate []dates = new MyDate[3];
dates[0] = new MyDate(22,7,1964);
dates[1] = new MyDate(1,1,2000);
dates[2] = new MyDate(22,12,1964);

静态初始化值

int[] a = {3,9,8};int[] a = new int[] {3,9,8}
MyDate[] dates = {
	new MyDate(22,7,1964),new MyDate(1,1,2000),new MyDate(22,12,1964)
};

a.length得知数组长度

增强for语句

可以方便的处理数组,集合中各元素

int[] ages = new int[10];
for ( int age : ages )
{//这种语句是只读式遍历
	System.out.println(age);
}

数组复制

数组复制System.arraycopy提供了数组元素复制功能:
System.arraycopy(source,1,dest,0,source.Length);
将source数组中第1个元素开始
复制到dest数组中第0个开始,一共复制source.Length这么长

二维数组

二维数组是数组的数组

int [][] a = { {1,2},{3,4,0,9},{5,6,7} };

int [][] t = new int [3][];
t[0] = new int [2];//开的数组不一定是完整的矩形
t[1] = new int [4];
t[2] = new int [3];

class Person
{
	String name;
	int age;
	void sayHello()
    {
		System.out.println(Hello! My name is” + name);
	}
}
  • 类=类头+类体
  • 类成员=字段(field)+方法(method)
    • 字段(field,属性,变量)
    • 方法(method,函数)
  • 方法=方法头+方法体

构造方法

Person( String n,int a)
{
	name = n;
	age = a;
}

多态

方法有相同的名字,编译时能识别出来
签名不同:参数个数不同或参数类型不同
通过方法重载可以实现多态

在方法及构造方法中可以使用this.+字段来调用本局部变量的值

类的继承

  • 一个类只能有一个继承的父类
  • 子类继承父类的状态和行为
    • 可以修改父类的状态或重载父类的行为
    • 可以添加新的状态和行为
  • Java的继承通过extends关键字来实现:
    class Student extends Person
    如果没有extends子句,则该类默认为java.lang.Object的子类
    所有的类都是间接或直接地继承java.lang.Object得到的

字段(属性,变量)

  • 字段的继承

    • 字类可以继承父类的所有字段
    • Student自动具有Person的属性(name,age)
  • 字段的隐藏

    子类重新定义一个与从父类那里继承来的域变量完全相同的变量,称为域的隐藏

  • 字段的添加

    在定义子类时,加上新的域变量,据可以使子类比父类多一些属性

    class Student extends Person
    {
        String school;
        int score;
    }
    

方法

  • 方法的继承

    父类的非私有方法也可以被子类自动继承
    Student自动继承Person的方法sayHello和isOlderThan

  • 方法的覆盖(Override)(修改)

    子类也可以重新定义与父类同名的方法,实现对父类方法的覆盖
    @Override的使用

    @Override
    void sayHello()
    {
        System.out.println("Hello! My name is" + name + ".My school is " + school);
    }
    

    通过方法的覆盖,能够修改对象同名方法的具体实现方法

  • 方法的添加

    子类可以新加一些方法,以针对子类实现相应的功能
    在类Student中,加入一个方法,对分数判断:

    boolean isGoodStudent()
    {
        return score >= 90;
    }
    
  • 方法的重载

    一个类中可以有几个同名的方法,这称为方法的重载(Overload)
    同时还可以重载父类的同名方法.与覆盖方法不同的是,重载不要求参数类型列表相同
    重载的方法实际是新加的方法

    在类Student中,重载一个名为sayHello的方法:

    void sayHelo(Student another)
    {
        System.out.println("Hi!");
        if( school.quals( another.school ))
        {
            System.out.println(" Schoolmates ");
        }
    }
    

super的使用

  • 使用super访问父类的域和方法

    由于继承,使用this可以访问父类的域和方法
    但有时为了明确地指明父类的域和方法,就要用关键字super

    父类Student有一个域age,在子类Student中用age,this.age,super.age来访问age是完全一样的

    void testThisSuper()
    {
        int a;
        a = age;
        a = this.age;
        a = super.age;
    }
    

    有时需要使用super以区别同名的域与方法

    • 使用super可以访问被子类所隐藏了的同名变量

    • 当覆盖父类的同名方法的同时,又要调用父类的方法,就必须使用super

      void sayHello()
      {
          super.sayHello();
          System.out.println("My school is" + school);
      }
      
  • 使用父类的构造方法

    构造方法是不能继承的
    比如,父类Person有一个构造方法Person(String,int)不能说子类Student也自动有一个构造方法Student(String,int)

    但是,子类在构造方法中,可以用super来调用父类的构造方法

    Student(String name,int age,String school)
    {
    	super(name,age);
        this.school=school;
    }
    

    使用时super只能放在第一句

public static void main( String [] args )
{
    Person p = new Person("Liming",50);//正常情况
    Student s = new Student("Wangqiang",20,"PKU");//正常情况
    Person p2 = new Student("Zhangyi",18,"THU");
    Student s2 = (Student) p2;
    
    Student s3 = (Student) p;
    
    p.sayHello(s);
    
    Person [] manypeople = new Person[100];
    manypeople[0] = new Person("Li",18);
    manypeople[1] = new Student("Wang",18,"PKU");
}

package pkg1[.pkg2[.pkg3…]];
import package

修饰符

访问修饰符

public private

同一个类中同一个包中不同包中的子类不同包中的非子类
privateyes
默认yesyes
protectedyesyesyes
publicyesyesyesyes

其它修饰符

abstract

基本含义修饰类修饰成员修饰局部变量
static静态的,非实例的,类的可以修饰内部类yes
final最终的,不可改变的yesyesyes
abstract抽象的,不可实例化的yesyes
  • static字段

    • 静态字段最本质的特点是
      他们是类的字段,不属于任何一个对象的实例
    • 他不保存在某个对象实例的内存区间,二十保存在类的内存区域的公共存储单元
    • 类变量名可以通过类名直接访问,也可以通过实例对象来访问,两种方法的结果是相同的
    • 如System类的in和out对象,就是属于类的域,直接用类名来访问,如System.in和System.out
    class Person
    //此时的totalNum代表人类的总人数,他与具体对象实例无关
    //从某种意义上讲,他可以用来表示全局变量,属于整个类的
    {
        static long totalNum;
        int age;
        String Name;
    }
    
  • final

    • final类
      这个类不能被继承,即不可能有子类
    • final方法
      final修饰符所修饰的方法,是不能被子类所覆盖的方法
    • final字段和局部变量
      他们的值一旦给定,就不能更改,是一个只读量,能且只能被赋值一次
    • 同时被static final两个修饰符所限定时候,它可以表示常量
    • 关于赋值
      • 定义static final域默认初始化为
        • 数值为0
        • boolean为false
        • 引用型为null
      • 定义final字段时,若不是static的域,则必须且只能赋值一次
      • 定义final局部变量时,也必须且只能复制一次
  • abstract类

    • abstract类
      凡是用abstract修饰符修饰的类被称为抽象类
      抽象类不能被实例化
    • abstract方法
      被abstract所修饰的方法叫抽象方法,抽象方法的作用在为所有子类定义一个统一的接口.
      对抽象方法只需声明,而不需实现,即用分号;而不是{}
      一旦某个类中包含了absract方法,则这个类必须声明为abstract类

接口

接口,某种特定的约定

  • 定义接口 interface
    所有方法都自动是public abstract
  • 实现接口 implements
    可以实现多继承
    与类的继承关系无关

面向接口编程

interface Collection
{
    void add(Object obj);
    void delete(Object obj);
    Object find(Object obj);
    int size();
}

枚举

enum Light{Red, Yellow, Green}

Light light = Light.Red;
swtch(light)
{
    case Red:
    	break;
}

Java中的枚举是用class来实现的,可以复杂的使用

完整定义

完整的类定义

[public][abstract|final] class className[extends superclassName]
[implemrnts InterfaceNameList]
{//类声明
    [public|protected|private][static][final][transient][volatile] type variableName;//成员变量生命,可为多个
    [public|protected|private][static][final|abstract][native][synchronized]
    	return Type methodName([paramList])//方法定义及实现,可为多个
    [throws exceptionList]
    {
    	statements
    }
}

完整的接口定义

[public] interface InterfaceName [extends superInterfaceList]
{//接口声明
    type constantName = value;//常量声明,可为多个
    return TypeMethodName([paraList]);//方法声明,可为多个
}

固定的声明方式

构造方法

className([paramlist])
{
    
}

main() 方法

public static void main(String args[])
{
    
}

finalize()方法

protected void finalize()throws throwable
{
    
}

完整的java源文件

package packageName;//指定文件中的类所在的包,0个或1个
import packageName.[className|*];//指定引入的类,0个或多个
public classDefinition//属性为public的类定义,0个或1个
interfaceDefinition and class Definition//接口或类定义,0个或多个
    
源文件的名字必须与属性为public的类的类名完全相同
在一个.java文件中,package语句和public类最多只能有1

变量及其传递

基本类型变量与引用型变量

基本类型:其值直接cunyu 变量中
引用型的变量除占据一定的内存空间外,它所引用的对象实体(由new创建)也要占据一定空间

public class MyDate {
    private int day;
    private int month;
    private int year;

    public MyDate(int y, int m, int d) {
        year = y;
        month = m;
        day = d;
    }

    void addYear() {
        year++;
    }

    public void display() {
        System.out.println(year + '-' + month + '-' + day);
    }

    public static void main(String args[]) {
        MyDate m = new MyDate(2003, 9, 22);
        MyDate n = m;
        n.addYear();
        m.display();
        n.display();
    }
}
//由于是new出来的变量,所以是一个引用的对象,故改变其中的一个会影响到所有的

字段变量与局部变量

  • 前者是在类中,后者是方法中定义的变量或方法的参变量

  • 从内存角度看

    • 存储位置,字段变量为对象的一部分,存在于堆中,局部变量存在于栈中。

    • 生命周期不同

    • 初始值:字段变量可以自动赋初值,局部变量则须显式赋值

      class Test()
      {
          int a;
          void m(){
              int b;
              System.out.println(b);//编译不能通过,需要初始化
          }
      }
      
  • 从语法角度来看

    • 字段变量属于类,可以被public,private,static,final修饰
    • 局部变量不能够被访问控制符及static修饰
    • 都可以被final修饰

变量的传递

调用方法时,要传递参数.在传递参数时,Java是值传递,即,是将表达式的值复制给形式参数.
对于引用型变量,传递的值是引用值,而不是复制对象实体(可以改变对象的属性)

public class TransByValue {
    public static void main(String[] args) {
        int a = 0;
        modify(a);
        System.out.println(a);//0

        int[] b = new int[1];
        modify(b);
        System.out.println(b[0]);//1
    }

    public static void modify(int a) {
        a++;//仅仅是传了个参数进来,对外面的a不影响
    }

    public static void modify(int[] b) {
        b[0]++;
        b = new int[5];
    }
}

变量的返回

方法的返回:

  • 返回基本类型
  • 返回引用类型。它就可以存取对象实体
Object getNewObject()
{
    Object obj = new Object();
    return obj;
}

调用时:object p = GetNewObject();

多态

  • 指一个程序中相同的名字表示不同的含义的情况
  • 两种情况
    • 编译时多态:
      重载(多个同名的不同方法)
    • 运行时多态:
      • 覆盖(子类对父类方法进行覆盖)
      • 动态绑定–虚方法调用
      • 在调用方法时,程序会正确地调用子类对象的方法
  • 多态的特点大大提高了程序的抽象程度和简洁性

上溯造型

是把派生类型当作基本类型处理

Person p = new Student();

void fun(Person p){...}
fun(new Person());

虚方法调用

用虚方法调用,可以实现运行时的多态

  • 子类重载了父类方法时,运行时系统根据调用该方法的实例的类型来决定哪个方法调用
  • 所有的非final类方法都会自动地进行动态绑定
import java.awt.*;

public class TestVirtualInvoke {
    static void doStuff(Shape s) {
        s.draw();
    }

    public static void main(String[] args) {
        Circle c = new Circle();
        Triangle t = new Triangle();
        Line l = new Line();
        doStuff(c);
        doStuff(t);
        doStuff(l);
    }
}

class Shape {
    void draw() {
        System.out.println("Shape Drawing");
    }
}

class Circle extends Shape {
    void draw() {
        System.out.println("Draw Circle");
    }
}

class Triangle extends Shape {
    void draw() {
        System.out.println("Draw Three Lines");
    }
}

class Line extends Shape {
    void draw() {
        System.out.println("Draw Line");
    }
}

动态类型确定

变量instanceof类型
结果是boolean值

class InstanceOf {
    public static void main(String[] args) {
        Object[] things = new Object[3];
        things[0] = new Integer(4);
        things[1] = new Double(3.14);
        things[2] = new String("2.09");
        double s = 0;
        for (int i = 0; i < things.length; i++) {
            if (things[i] instanceof Integer)//判断其是不是个整数
                s += ((Integer) things[i]).intValue();
            else if (things[i] instanceof Double)//判断其是不是个双精度
                s += ((Double) things[i]).doubleValue();
        }
        System.out.println("sum=" + s);
    }
}

什么时候不是虚方法

Java中,普通方法是虚方法
但static,private方法不是虚方法调用
static,private与虚方法编译后用的指令是不同的

class JavaP3methods {
    void f() {
    }

    private void p() {
    }

    static void s() {
    }

    public static void main(String... argv) {
        JavaP3methods obj = new JavaP3methods();
        obj.f();
        obj.p();
        obj.s();
    }
}

三种非虚的方法

  • static方法,以声明的类型为准,与实例类型无关
  • private方法子类看不见,也不会被虚化
  • final方法子类不能覆盖,不存在虚化问题
class TestStaticInvoke {
    static void doStuff(Shape s) {
        s.draw();
    }

    public static void main(String[] args) {
        Circle c = new Circle();
        Triangle t = new Triangle();
        Line l = new Line();
        doStuff(c);//由于是定义的是static类所以只跟你定义的类型有关系
        doStuff(t);//此处都是跟shape有关
        doStuff(l);

        Shape s = new Circle();
        doStuff(s);//声明了shape类故只能输出ShapeDrawing
        s.draw();

        Circle c2 = new Circle();
        c2.draw();//声明了circle类之后调用了其本身的方法故输出DrawCircle
    }
}

class Shape {
    static void draw() {
        System.out.println("Shape Drawing");
    }
}

class Circle extends Shape {
    static void draw() {
        System.out.println("Draw Circle");
    }
}

class Triangle extends Shape {
    static void draw() {
        System.out.println("Draw Three Lines");
    }
}

class Line extends Shape {
    static void draw() {
        System.out.println("Draw Line");
    }
}
/*
Shape Drawing
Shape Drawing
Shape Drawing
Shape Drawing
Shape Drawing
Draw Circle
*/

构造方法

对象都有构造方法,如果没有,编译器加一个default构造方法

  • 调用本类或父类的构造方法

    • this调用本类的其他构造方法
    • super调用直接父类的构造方法
    • this或super要放在第一条语句,且只能够有一条
  • 如果没有this及super,则编译器自动加上super(),即调用直接父类不带参数的构造方法

  • 因为必须令所有父类的构造方法都得到调用,否则整个对象的构造就可能不正确

    class ConstructCallThisAndSuper {
        public static void main(String[] args) {
            Person p = new Graduate();//创建一个人p,他是一个研究生
        }
    }
    
    class Person {
        String name;
        int age;
    
        Person() {
        }
    
        Person(String name, int age) {
            this.name = name;
            this.age = age;
            System.out.println("In Person(String,int)");
        }
    }
    
    class Student extends Person {
        String school;
    
        Student() {
            this(null, 0, null);
            System.out.println("In Student()");
        }
    
        Student(String name, int age, String school) {
            super(name, age);
            this.school = school;
            System.out.println("In Student(String,int,String)");
        }
    }
    
    class Graduate extends Student {
        String teacher = "";
    
        Graduate() {
            //super();加上与不加上都可,编译器会自动的加上super,因为他会继承父类
            System.out.println("In Graduate()");
        }
    }
    /*
    会调用一系列的构造方法
    In Person(String,int)
    In Student(String,int,String)
    In Student()
    In Graduate()
     */
    

    一个问题

    class A{
        A(int a){
            
        }
    }
    class B extends A{
        B(String s){
            //编译不能通过
        }
    }
    
    编译器会自动调用
    B(String s){
        super();
    }出错
    

    解决方法:

    • 在B的构造方法中加入super(3);
    • 在A中加入一个不带参数的构造方法,A(){}
    • 去掉A中全部的构造方法,则编译器会自动加入一个不带参数的构造方法,称为默认的构造方法。

创建对象的初始化

p = new Person(){{ age = 18; name = "李明";}};
注意双括号

实例初始化与静态初始化

实例初始化

{语句}

在类中直接写,实例初始化,先于构造方法中的语句执行

静态初始化

static {语句}

静态初始化,在第一次使用这个类时执行,但其执行的具体时机是不确定的,但可以肯定的是:总是先于实例的初始化

class InitialTest {
    public static void main(String[] args) {
        new InitialTest2(6);
    }

    int n = 10;  //step2
    {
        n++;
        System.out.println("InitialTest..." + n);
    }

    static int x;

    static {
        x++;
        System.out.println("static..." + x);
    }

}

class InitialTest2 extends InitialTest {
    InitialTest2(int a) {//构造函数
        this.a = a;
        System.out.println("this.a=" + a);
    }

    int a;
    {
        System.out.println("InitialTest2..." + this.a);
    }

    static {
        x++;
        System.out.println("static2..." + x);
    }
}
/*
先构造一个子类,但是static初始化先运行
然后运行实例初始化,最后在构造函数
static...1
static2...2
InitialTest...11
InitialTest2...0
this.a=6
 */

构造方法的执行过程

  1. 调用本类或父类的构造方法,直至最高一层(Object)
  2. 按照声明顺序执行字段的初始化赋值
  3. 执行构造函数中的各语句

简单的说:先父类构造,再本类成员赋值,最后执行构造方法中的语句

class ConstructSequence {
    public static void main(String[] args) {
        Person p = new Student("李明", 18, "北大");
    }
}

class Person {
    String name = "未命名";  //step 2
    int age = -1;

    Person(String name, int age) {
        super(); //step 1
        //step 3
        System.out.println("开始构造Person(),此时this.name=" + this.name + ",this.age=" + this.age);
        this.name = name;
        this.age = age;
        System.out.println("Person()构造完成,此时this.name=" + this.name + ",this.age=" + this.age);
    }
}

class Student extends Person {
    String school = "未定学校"; //step2

    Student(String name, int age, String school) {
        super(name, age);  //step 1
        //step 3
        System.out.println("开始构造Student(),此时this.name=" + this.name + ",this.age=" + this.age + ",this.school=" + this.school);
        this.school = school;
        System.out.println("Student()构造完成,此时this.name=" + this.name + ",this.age=" + this.age + ",this.school=" + this.school);
    }
}
/*
开始构造Person(),此时this.name=未命名,this.age=-1
Person()构造完成,此时this.name=李明,this.age=18
开始构造Student(),此时this.name=李明,this.age=18,this.school=未定学校
Student()构造完成,此时this.name=李明,this.age=18,this.school=北大
 */

一个问题

构造方法内部调用别的方法,这个方法恰好是个虚方法,结果如何?

class ConstructInvokeMetamorph {
    public static void main(String[] args) {
        Person p = new Student("李明", 18, "北大");
    }
}

class Person {
    String name = "未命名";
    int age = -1;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
        sayHello();
//在此时调用的函数为虚函数,是子类的函数,而此时学校的信息还没有复制好,会导致出现错误
    }

    void sayHello() {
        System.out.println("我是一个人,我名叫:" + name + ",年龄为:" + age);
    }
}

class Student extends Person {
    String school = "未定学校";

    Student(String name, int age, String school) {
        super(name, age);
        this.school = school;
    }

    void sayHello() {
        System.out.println("我是学生,我名叫:" + name + ",年龄为:" + age + ",学校在:" + school);
    }
}
/*
我是学生,我名叫:李明,年龄为:18,学校在:null
*/

对象清除垃圾回收

垃圾回收,对象回收是由Java虚拟机的垃圾回收线程来完成的
为什么系统知道对象是否为垃圾:任何对象都有一个引用计数器,当其值为0时,说明该对象可以回收

System.gc()方法,他是System类的static方法,它可以要求系统进行垃圾回收,但他仅仅只是‘建议’

  • Java中没有析构方法

  • 但Object的finalize()有类似功能

    • 系统在回收时会自动调用对象的finalize()方法
    • protected void finalize() throws Throwable{}
  • 子类的finalize()方法

    • 可以在子类的finalize()方法释放系统资源
    • 一般来说,子类的finalize()方法中应该调用父类的finalize()方法,以保证父类的清理工作能够正常进行。
  • 由于finalize()方法的调用时机不确定,所以一般不用finalize()

  • 关闭打开的文件,清除一些非内存资源等工作需要进行处理可以使用tyr-with-resource语句

  • 对于实现了java.lang.AutoCloseable的对象

    try( Scanner scanner = new Scanner(...) ){
        ...
    }
    会自动调用其clode()方法,相当于
    finally{
        Scanner.close();
    }
    

内部类与匿名类

内部类

定义

  • 将类的定义class xxxx{…}置入一个类的内部即可
  • 编译器生成xxxx$xxxx这样的class文件
  • 内部类不能够与外部类同名

使用

  • 在封装它的类的内部使用内部类,与普通类的使用方法相同
  • 在其他地方使用
    • 类名前要冠以外部类的名字
    • 在new创建内部类时,也要在new前面冠以对象变量
      外部对象名.new 内部类名(参数)
class TestInnerClass {
    public static void main(String[] args) {
        Parcel p = new Parcel();
        p.testShip();

        Parcel.Contents c = p.new Contents(33);//要加上外部的类名
        Parcel.Destination d = p.new Destination("Hawii");
        p.setProperty(c, d);
        p.ship();
    }
}

class Parcel {
    private Contents c;
    private Destination d;

    class Contents {//内部类
        private int i;

        Contents(int i) {
            this.i = i;
        }

        int value() {
            return i;
        }
    }

    class Destination {
        private String label;

        Destination(String whereTo) {
            label = whereTo;
        }

        String readLabel() {
            return label;
        }
    }

    void setProperty(Contents c, Destination d) {
        this.c = c;
        this.d = d;
    }

    void ship() {
        System.out.println("move " + c.value() + " to " + d.readLabel());
    }

    public void testShip() {
        c = new Contents(22);
        d = new Destination("Beijing");
        ship();
    }
}

内部类使用外部类

public class TestInnerThis {
    public static void main(String args[]) {
        A a = new A();
        A.B b = a.new B();
        b.mb(333);
    }
}

class A {
    private int s = 111;

    public class B {
        private int s = 222;

        public void mb(int s) {
            System.out.println(s); // 局部变量s
            System.out.println(this.s); // 内部类对象的属性s
            System.out.println(A.this.s); //  外层类对象属性s
        }
    }
}

内部类的修饰符

内部类与类中的字段、方法一样是外部类的成员,它的前面也可以有访问控制符和其他修饰符

  • 访问控制符:public,protected,默认及private。
    外部类只能够使用public修饰或者默认

  • final,abstract

  • static修饰内部类,表明内部类实际是一种外部类

    • 实例化static类时,在new前面不需要用对象实例变量

    • static类中不能访问其外部类的非static的字段及方法,既只能够访问static成员

    • static方法中不能访问非static的域及方法,也不能够不带前缀地new一个非static的内部类

    •   class TestInnerStatic {
            public static void main(String[] args) {
                A.B a_b = new A().new B();
                A a = new A();
                A.B ab = a.new B();
        
                Outer.Inner oi = new Outer.Inner();
                //Outer.Inner oi2 = Outer.new Inner();  //!!!error   
                //Outer.Inner oi3 = new Outer().new Inner(); //!!! error
            }
        }
        
        class A {
            private int x;
        
            void m() {
                new B();
            }
        
            static void sm() {
                //new B();  // error!!!!
            }
        
            class B {
                B() {
                    x = 5;
                }
            }
        }
        
        class Outer {
            static class Inner {
            }
        }
      

局部类

在一个方法中定义类,方法中的内部类

class TestInnerInMethod {
    public static void main(String[] args) {
        Object obj = new Outer().makeTheInner(47);
        System.out.println("Hello World!" + obj.toString());
    }
}

class Outer {
    private int size = 5;

    public Object makeTheInner(int localVar) {
        final int finalLocalVar = 99;
        class Inner {
            public String toString() {
                return (" InnerSize: " + size +
                        // " localVar: " + localVar +   // Error! 
                        " finalLocalVar: " + finalLocalVar
                );
            }
        }
        return new Inner();
    }
}
  • 同局部变量一样,方法中的内部类
    • 不能够用public,private,protected,static修饰
    • 但可以被final或者abstract修饰
  • 可以访问其外部类的成员
  • 不能够访问该方法的局部变量,除非是final局部变量

匿名类

  • 一种特殊的内部类
  • 没有类名,在定义类的同时就生成该对象的一个实例
  • 一次性使用的类
class TestInnerAnonymous {
    public static void main(String[] args) {
        Object obj = new Outer().makeTheInner(47);
        System.out.println("Hello World!" + obj.toString());
    }
}

class Outer {
    private int size = 5;

    public Object makeTheInner(int localVar) {
        final int finalLocalVar = 99;
        return new Object() {
            public String toString() {
                return (" InnerSize: " + size +
                        " finalLocalVar: " + finalLocalVar
                );
            }
        };
    }
}
  • 不取名字,直接用其父类或接口的名字
    也就是说,该类是父类的一个子类,或者实现了一个接口
  • 类的定义的同时就创建实例,即类的定义前面有一个new
    • new 类名 或 接口名(){...}
    • 不使用关键词class,也不使用extends及implements
  • 在构造对象时使用父类构造方法
    • 不能够定义构造方法,因为无名字
    • 如果new对象时,要带参数,则使用父类的构造方法

Lambda表达式

  • (参数) -> 结果
  • (String s) -> s.length()
  • x -> x*x
  • () -> {System.out.println(“aaa”);}

大体相当于其他语言的 “匿名函数” 或 “函数指针”
在Java中它实际上是 “匿名类的一个实例”

Runnable dolt = new Runnable(){
    public void run(){
        System.out.println("aaa");
    }
}
new Thread(dolt).start();

就可以写成

Runnable dolt = () -> System.out.println("aaa");
new Thread( dolt ).start();

甚至可以写为

new Thread(() -> System.out.println("aaa")).start();

例如:
写一个积分函数

double d = Integral( new Fun() {
    public double fun(double x){
        return Math.sin(x);
    }
}, 0, Math.PI, 1e-5);

可以写为

double d = Integral( x-> Math.sin(x) , 0, Math.PI, 1e-5);
@FunctionalInterface
interface Fun {
    double fun(double x);
}

public class LambdaIntegral {
    public static void main(String[] args) {
        double d = Integral(new Fun() {
            public double fun(double x) {
                return Math.sin(x);
            }
        }, 0, Math.PI, 1e-5);

        d = Integral(x -> Math.sin(x),
                0, Math.PI, 1e-5);
        System.out.println(d);

        d = Integral(x -> x * x, 0, 1, 1e-5);
        System.out.println(d);

    }

    static double Integral(Fun f, double a, double b, double eps)// ���ּ���
    {
        int n, k;
        double fa, fb, h, t1, p, s, x, t = 0;

        fa = f.fun(a);
        fb = f.fun(b);

        n = 1;
        h = b - a;
        t1 = h * (fa + fb) / 2.0;
        p = Double.MAX_VALUE;

        while (p >= eps) {
            s = 0.0;
            for (k = 0; k <= n - 1; k++) {
                x = a + (k + 0.5) * h;
                s = s + f.fun(x);
            }

            t = (t1 + h * s) / 2.0;
            p = Math.abs(t1 - t);
            t1 = t;
            n = n + n;
            h = h / 2.0;
        }
        return t;
    }
}

能写成lambda的接口要求包含最多只能有一个抽象函数

@FunctionalInterface
interface Fun{
    double fun( double x );
}

装箱,枚举,注解

基本类型包装

将基本类型包装成Object引用类型
Interger包含了八类
Boolean,Byte,Short,Character,Integer,Long,Float,Double

装箱Integer I = 10;
拆箱int i = I;

主要方便用于集合中
Object [] are = { 1, “aaa”};

枚举

  • 一种特殊的class类型
  • 在简单的情况下,用法与其他语言的enum相似
    • enum Light {Red, Yellow, Green };
    • Light light = Light.Red;
  • 但实际上,它生成了class Light extends java.lang.Enum

自定义枚举

可以在enum定义体中,添加字段,方法,构造方法

enum Direction
{
    EAST("东", 1),
    SOUTH("南", 2),
    WEST("西", 3),
    NORTH("北", 4);
    
    private Direction( String desc, int num){
        this.desc = desc;
        this.num = num;
    }
    private String desc;
    private int num;
    public String getDesc(){return desc;}
    public int getNum(){return num;}
}

注解

在各种语法要素上加上附加信息
都是java.lang.annotation.Annotation的子类

常用的注解

@Override 表示覆盖父类的方法
@Deprecated 表示过时的方法
@SuppressWarnings 表示让编译器不产生警告

自定义注解,比较复杂

public @interface Auther{
    String name();
}

引用与指针

引用实质就是指针
但是它是受控制的,安全的

  • 会检查空指针
  • 没有指针运算 *(p+5)
  • 不能访问没有引用到的内存
  • 自动回收垃圾
  1. 传地址 -> 对象

    • 引用类型,引用本身就相当于指针
      可以用来修改对象的属性,调用对象的方法
    • 基本类型:没用对应的
      如交换两个整数
      void swap(int x, int =y) {int t = x; x = y; y =t; }
      int a = 8, b = 9; swap( a, b);
      一种变通的办法,传出一个有两个分量x,y的对象
  2. 指针运算 -> 数组
    *(p + 5)则可以用args[5]

  3. 函数指针 -> 接口,Lambda表达式
    求积分,线程,回调函数,时间处理

  4. 指向结点的指针 -> 对象的引用

    class Node{
        object data;
        Node next;
    }//链表
    
    import java.io.IOException;
    
    public class List {
    	private Node Head = null;
    	private Node Tail = null;
    	private Node Pointer = null;
    	private int Length = 0;
    
    	public void deleteAll() {
    		Head = null;
    		Tail = null;
    		Pointer = null;
    		Length = 0;
    	}
    
    	public void reset() {
    		Pointer = null;
    	}
    
    	public boolean isEmpty() {
    		return (Length == 0);
    	}
    
    	public boolean isEnd() {
    		if (Length == 0) throw new java.lang.NullPointerException();
    		else if (Length == 1) return true;
    		else return (cursor() == Tail);
    	}
    
    	public Object nextNode() {
    		if (Length == 1) throw new java.util.NoSuchElementException();
    		else if (Length == 0) throw new java.lang.NullPointerException();
    		else {
    			Node temp = cursor();
    			Pointer = temp;
    			if (temp != Tail) return (temp.next.data);
    			else throw new java.util.NoSuchElementException();
    		}
    	}
    
    	public Object currentNode() {
    		Node temp = cursor();
    		return temp.data;
    	}
    
    	public void insert(Object d) {
    		Node e = new Node(d);
    		if (Length == 0) {
    			Tail = e;
    			Head = e;
    		} else {
    			Node temp = cursor();
    			e.next = temp;
    			if (Pointer == null) Head = e;
    			else Pointer.next = e;
    		}
    		Length++;
    	}
    
    	public int size() {
    		return (Length);
    	}
    
    	public Object remove() {
    		Object temp;
    		if (Length == 0) throw new java.util.NoSuchElementException();
    		else if (Length == 1) {
    			temp = Head.data;
    			deleteAll();
    		} else {
    			Node cur = cursor();
    			temp = cur.data;
    			if (cur == Head) Head = cur.next;
    			else if (cur == Tail) {
    				Pointer.next = null;
    				Tail = Pointer;
    				reset();
    			} else Pointer.next = cur.next;
    			Length--;
    		}
    		return temp;
    	}
    
    	private Node cursor() {
    		if (Head == null) throw new java.lang.NullPointerException();
    		else if (Pointer == null) return Head;
    		else return Pointer.next;
    	}
    
    	public static void main(String[] args) throws IOException{
    		List a = new List();
    		for (int i = 1; i <= 10; i++) a.insert(new Integer(i));
    		System.out.println(a.currentNode());
    		while (!a.isEnd()) System.out.println(a.nextNode());
    		a.reset();
    		while (!a.isEnd()) {
    			a.remove();
    		}
    		a.remove();
    		a.reset();
    		if (a.isEmpty()) System.out.println("There  is  no  Node  in  List  n");
    		System.out.println("You  can  press  return  to  quitn");
    		try {
    			System. in .read();
    		} catch(IOException e) {}
    		
    	}
    }
    
    class Node {
    	Object data;
    	Node next;
    
    	Node(Object d) {
    		data = d;
    		next = null;
    	}
    }
    
  5. 使用JNI
    Java Native Interface (JNI)
    它允许JAVA代码和其他语言写的代码交互

相等还是不等

==

  • 基本类型

    • 数值类型:转换后比较

    • 浮点数,最好不直接==
      Double.NAN == Double.NAN结果为false

    • boolean型无法与int相比较

    •   Integer i = new Integer(10);
        Integer j = new Integer(10);
        System.out.println( i==j );//false,因为对象是两个
        
        Integer m = 10;
        Integer n = 10;
        System.out.println( m==n );//true,因为对象有缓存
        
        Integer p = 200;
        Integer q = 200;
        System.out.println( p==q );//false,因为对象是两个
        
        -128 127
      
  • 枚举类型
    内部进行了唯一实例化,所以可以直接判断

  • 引用对象

    • 是直接看两个引用是否一样
    • 如果要判断内容是否一样,则要重写equals方法
    • 如果重写equals方法,则最好重写hashCode()方法
  • String对象
    判断相等,一定不要用==,要用equals
    但是字符串常量(String literal)及字符串常量会进行内部话(interned),相同的字符串常量是==的

    class TestStringEquals{
    	public static void main(String[] args) {
    		String hello = "Hello", lo = "lo";
    		System.out.println( hello == "Hello");  //true
    		System.out.println( Other.hello == hello ); //true
    
    		System.out.println( hello == ("Hel"+"lo") ); //true
    		System.out.println( hello == ("Hel"+lo) ); //false
    		
    		System.out.println( hello == new String("Hello")); //false
    		System.out.println( hello == ("Hel"+lo).intern()); //true
    	}
    }
    class Other { static String hello = "Hello"; }
    

异常处理

try{
    语句组
}catch(Exception ex){
    异常处理语句组;
}
import java.io.*;
public class ExceptionForNum 
{
	public static void main(String[] args) 
	{
		try{
			BufferedReader in = new BufferedReader(
				new InputStreamReader( System.in ) );
			System.out.print("Please input a number: ");
			String s = in.readLine();
			int n = Integer.parseInt( s );
		}catch(IOException ex){
			ex.printStackTrace();
		}catch(NumberFormatException ex){
			ex.printStackTrace();
		}
	}
}

JAVA中处理异常

  • 抛出异常
  • 运行时系统在调用栈中查找
    从生成异常的方法开始进行回溯,直到找到
  • 捕获异常的代码

相关语句

  • 抛出异常
    throw 异常对象;

  • 捕获异常

    try{
        语句组
    }catch(异常类名 异常形式参数名){
        异常处理语句组;
    }catch(异常类名 异常形式参数名){
        异常处理语句组;
    }finally{
        异常处理语句组;
    } 其中,catch语句可以0至多个,可以没有finally语句
    

异常类型

  • Throwable

    • Error:JVM的错误

    • Exception:异常,一般所说的异常是指Exception及其子类

      • 构造方法

        public Exception();
        public Exception(String message);
        Exception(String message, Throwable cause);
        
      • 方法

        getMessage()
        getCause()
        printfStackTrace()
        

多异常处理

子类异常排在父类前面

finally

无论是否有异常都要执行,即使其中有break等语句

class JavaPTryCatchFinally {
    public static void main(String[] args) {
        int a = 100;
        try {
            a = 200;
        } catch (IndexOutOfBoundsException ex) {
            a = 300;
        } catch (Exception ex) {
            a = 400;
        } finally {
            a = 500;
        }
        a = 600;
    }
}
public class TestTryFinally {
    public static String output = "";

    public static void foo(int i) {
        try {
            if (i == 1) {
                throw new Exception();
            }
            output += "1";
        } catch(Exception e) {
            output += "2";
            return;
        } finally {
            output += "3";
        }
        output += "4";
    }

    public static void main(String args[]) {
        //foo(0);
        //System.out.print(output + " ");
        foo(1);
        System.out.println(output);
    }
}

受检异常

  • Exception分两种

    • RuntimeException及其子类,可以不明确处理
    • 否则,成为受检的异常(checked Exception)
  • 受检的异常,要求明确进行语法处理

    • 要么捕(catch)

    • 要么抛(throws),在方法的签名后面用throws ****来

      • 在子类中,如果要覆盖父类的一个方法,若父类中的方法声明了throws异常,则子类的方法也可以throws异常
      • 也可以抛出异常(更具体的异常),但不能抛出更一般的异常
      import java.io.*;
      public class ExceptionTrowsToOther{
      	public static void main(String[] args){
      	
      		try{
      			System.out.println("====Before====");
      		 	readFile();
      			System.out.println("====After====");
      		 }catch(IOException e){ System.out.println(e); }
      	}
      
      	public static void readFile()throws IOException {
      		FileInputStream in=new FileInputStream("myfile.txt");
      		int b;	
      		b = in.read();
      		while(b!= -1)   {
      			System.out.print((char)b);
      			b = in.read();
      		}
      		in.close();	
      	}
      }
      
  •   try(类型 变量名 = new 类型()){
          ...
      }
      将会添加了finally {
          变量.close();
      }
    
    import java.io.*;
    class TryWithResourcesTest {
        public static void main(String ... args)
    		throws IOException
    	{
    		String path = "c:\\aaa.txt";
    		System.out.println( ReadOneLine1( path ) );
    		System.out.println( ReadOneLine2( path ) );
        }
    	static String ReadOneLine1(String path){
    		BufferedReader br=null;
            try {
                br=new BufferedReader(new FileReader(path));
                return br.readLine();
            } catch(IOException e) {
                e.printStackTrace();
            } finally {
                if(br!=null){
    				try{ 
    					br.close();
    				}catch(IOException ex){
    				}
    			}
            }
    		return null;
    	}
    	static String ReadOneLine2(String path)
    		throws IOException
    	{
    		try(BufferedReader br= new BufferedReader(new FileReader(path))){
                return br.readLine();
            }
    	}
    }
    

自定义异常

  1. 将当前捕获的异常再次抛出
    throw e
  2. 重新生成一个异常,并抛出,如:
    throw new Exception(“some message”);
  3. 重新生成并抛出一个新异常,该异常中包含了当前异常信息,
    Throw new Exception(“some message”,e);
    可用e.getCause()来得到内部异常
public class ExceptionCause {
	public static void main(String [] args)	{
		try 
		{
			BankATM.GetBalanceInfo( 12345L);
		}catch(Exception e)	{
			System.out.println("something wrong: " + e);
			System.out.println("cause:" + e.getCause());
		}
	}
}

class DataHouse {
	public static void FindData( long ID)
		throws DataHouseException
	{
		if( ID>0 && ID<1000)
			System.out.println( "id: " + ID );
		else
			throw new DataHouseException("cannot find the id");
	}
}
class BankATM{
	public static void GetBalanceInfo( long  ID)
		throws MyAppException
	{
		try 
		{
			DataHouse.FindData(ID);
		}catch (DataHouseException e) {
			throw new MyAppException("invalid id",e);
		}
	}
}
class DataHouseException extends Exception {
	public DataHouseException( String message ) {
		super(message);
	}
}
class MyAppException extends Exception {
	public MyAppException (String message){ 
		super (message); 
	}
	public MyAppException (String message, Exception cause) {
		super(message,cause);
	}   
}

断言

assert格式:

  • assert 表达式;
  • assert 表达式:信息

再调试程序时
如果表达式不为true,则程序会产生异常,并输出相关的错误信息

class Assertion {
	public static void main(String[] args)	{
		assert hypotenuse(3,4)==5 : "算法不正确";
	}
	static double hypotenuse( double x, double y ){
		return Math.sqrt( x*x + y*y + 1);
	}
}

测试函数

@Test来标注测试函数
在测试中常用的语句如下:

  • fail(信息);//表示程序出错

  • assertEqauls(参数1, 参数2);//表示程序要保证两个参数相等

  • assertNull(参数);//表示参数要为null

    @Test
    public void testSum2(){
        HelloWorld a = new HelloWorld();
        assertEquals(a.sum(0,100),100);
        //fail("Not yet implemented");
    }
    

    语言基础

JAVA基础类库

  • Java.lang  JAVA核心类库
    JAVA是自动导入java.lang.*的
  • Java.util 实用工具
  • Java.io 标准输入/输出类库
  • Java.awt java.swing 图形用户界面(GUI)的类库
  • Java.net 网络功能的类库
  • Java.sql 数据库访问的类库

字符串

  • String类
    创建之后不会再做修改和变动,即immutable

  • StringBuffer,StringBuilder类
    创建之后允许再做更改和变化
    其中StringBuilder是JDK1.5增加的,它是非线程安全的

  • 特别注意,在循环中使用String+=可能会带来效率的问题

    import java.util.*;
    class StringAndStringBuffer 
    {
    	public static void main(String[] args) 
    	{
    		String a = "a";
    		String s = "";
    		StringBuffer sb = new StringBuffer();
    
    		final int N = 10000;
    
    		long t0 = System.currentTimeMillis();
    		for( int i=0; i<N; i++) s+=a;
    		long t1 = System.currentTimeMillis();
    		for( int i=0; i<N; i++) sb.append(a);
    		long t2 = System.currentTimeMillis();
    
    		System.out.println(t1-t0);
    		System.out.println(t2-t1);
    	}
    }
    
  • String类对象保存不可修改的Unicode字符序列

    • 创建: concat,replace,replaceAll,substring,toLowerCase,toUpperCase,trim,toString
    • 查找:endsWith,startsWith,indexOf,lastIndexOf
    • 比较:equals,equalsIgnoreCase
    • 字符串及长度:charArt,length
  • StringBuffer类对象保存可修改的Unicode字符序列

    • StringBuilder类似,效率高,不考虑线程安全性

    • 构造方法

      • StringBuffer()
      • StringBuffer(int capacity)
      • StringBuffer(String initialString)
    • 修改方法:
      append,insert,reverse,setCharart,setLength

    •   class TestStringMethod
        {
        	public static void main(String[] args) 
        	{
        		String s = new String( "Hello World" );
        
        		System.out.println( s.length() );
        		System.out.println( s.indexOf('o') );
        		System.out.println( s.indexOf("He") );
        		System.out.println( s.startsWith("He") );
        		System.out.println( s.equals("Hello world") );
        		System.out.println( s.equalsIgnoreCase("Hello world") );
        		System.out.println( s.compareTo("Hello Java") );
        		System.out.println( s.charAt(1) );
        		System.out.println( s.substring(0,2) );
        		System.out.println( s.substring(2) );
        		System.out.println( s.concat("!!!") );
        		System.out.println( s.trim() );
        		System.out.println( s.toUpperCase() );
        		System.out.println( s.toLowerCase() );
        		System.out.println( s.replace('o', 'x' ) );
        		
        		System.out.println( s );  //注意,s本身没有改变
        	}
        }
      
  • 字符串分割

    • java.util.StringToken类提供了对字符串进行分割的功能

    • 构造
      StringTokenizer(String str,String delim);

    • 方法:

      • public int countTokens();//分割串的个数
      • public boolean hasMoreTokens();//是否还有分割串
      • public String nextToken();//得到下一分割串
    •   import java.util.*;
        class TestStringTokenizer 
        {
        	public static void main(String[] args) 
        	{
        		StringTokenizer st = new StringTokenizer("this is a test", " ");
        		while (st.hasMoreTokens()) {
        			System.out.println(st.nextToken());
        		}
        		st = new StringTokenizer("253,197,546", ",");
        		double sum = 0;
        		while (st.hasMoreTokens()) {
        			sum += Double.parseDouble(st.nextToken());
        		}
        		System.out.println( sum );
        	}
        }
      

日期类

calendar通过getTime()得到Date,Date通过getTime()得到long

  • Calendar

    • 得到一个实例 Calendar.getInstance()//Locale.ZH
    • .get(DAY_OF_MONTH) .getDisplayName(DAY_OF_WEEK)
    • .set .add(HOUR,1) .roll(MONTH,5)
    • .setTime(date) .getTime()
  • Date

    • New Date(), new Date(System.currentTimeMillis())
    • .setTime(long) .getTime()
  • SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”)
    .format .parse

  •   import java.util.Calendar;
      import java.util.Date;
      import java.text.SimpleDateFormat;
      import java.util.Locale;
      import static java.util.Calendar.*;
      
      class CalendarDate 
      {
      	public static void main(String[] args) throws java.text.ParseException
      	{
      		Calendar calendar = Calendar.getInstance();
      		calendar.roll( MONTH, 1);
      		System.out.println( calendar.get(MONTH) + "月" + calendar.get( DAY_OF_MONTH ) + "日");
      
      		Date date = new Date();
      		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
      		System.out.println( formatter.format(date ));
      
      		date = new SimpleDateFormat("yyyy-MM-dd").parse( "2013-4-23" );
      		calendar.setTime( date );
      		System.out.println( calendar.getDisplayName(DAY_OF_WEEK, LONG, Locale.CHINA) );
      
      	}
      }
    
  • JDK8以后

    import java.time.*;
    import java.time.format.*;
    
    class CalendarDate8{
    	public static void main(String[] args) throws java.text.ParseException
    	{
    		//使用默认时区时钟瞬时时间创建 Clock.systemDefaultZone() -->即相对于 ZoneId.systemDefault()默认时区  
            LocalDateTime now = LocalDateTime.now();
            System.out.println(now);
    		
    		//自定义时区  
            LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Europe/Paris"));
            System.out.println(now2);//会以相应的时区显示日期  
    
    		//构造一个对象  
            LocalDateTime d1 = LocalDateTime.of(2013, 12, 31, 23, 59, 59);
    
    		//解析String--->LocalDateTime  
            LocalDateTime d4 = LocalDateTime.parse("2013-12-31T23:59:59");
            System.out.println(d4);
    
    		//使用DateTimeFormatter API 解析 和 格式化  
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
            LocalDateTime d6 = LocalDateTime.parse("2013/12/31 23:59:59", formatter);
            System.out.println(formatter.format(d6));
    
    		//时间获取的一部分
            System.out.println(d6.getYear());
            System.out.println(d6.getMonth()); //这不是整数,而是枚举
            System.out.println(d6.getDayOfYear());
            System.out.println(d6.getDayOfMonth());
            System.out.println(d6.getDayOfWeek());
            System.out.println(d6.getHour());
            System.out.println(d6.getMinute());
            System.out.println(d6.getSecond());
            System.out.println(d6.getNano()); //纳秒
    		
    		//时间增减  
            LocalDateTime d7 = d6.minusDays(1);
            LocalDateTime d8 = d6.plusHours(1).plusMinutes(30);
    		System.out.println(d7);
    		System.out.println(d8);
    	}
    }
    

集合

  • collection接口:有两个子接口
    List:记录元素保存顺序,且允许有重复元素
    Set:不记录元素的保存顺序,且不允许有重复元素

  • Map接口,映射
    键-值对的集合

  • List接口

    import java.util.*;
    public class TestArrayList{
    	public static void main(String[] args) {
    		ArrayList h = new ArrayList();
    		h.add("1st");
    		h.add("2nd");
    		h.add(new Integer(3));
    		h.add(new Double(4.0));
    		h.add("2nd");      // 重复元素, 加入
    		h.add(new Integer(3)); // 重复元素,加入
    		m1(h);
    	}
    	public static void m1(List s){
    		System.out.println(s);
    	}
    }
    //本应用程序输出结果如下[1st, 2nd, 3, 4.0, 2nd, 3]
    
  • 使用增强for语句

    for(Photo photo:album){
        System.out.println(photo.toString());
    }
    
  •   import java.util.*;
      class TestList {
      	public static void main(String[] args){ 
      		//List<Photo> album = new ArrayList<>(); 
      		List<Photo> album = new LinkedList<>(); 
      
      		album.add( new Photo("one",new Date(), "classroom"));
      		album.add( new Photo("two",new Date(), "library"));
      		album.add( new Photo("three",new Date(), "gym"));
      		album.add( new Photo("three",new Date(), "dorm"));
      
      		Iterator<Photo> iterator = album.iterator();
      		while(iterator.hasNext()){
      			Photo photo = iterator.next();
      			System.out.println( photo.toString() );
      		}
      
      		for( Photo photo : album ){  
      			System.out.println( photo );
      		}
      	}
      }
      class Photo {
      	String title;
      	Date date;
      	String memo;
      	Photo(String title, Date date, String memo){
      		this.title = title;
      		this.date = date;
      		this.memo = memo;
      	}
      	@Override
      	public String toString(){
      		return title + "(" + date + ")" + memo;
      	}
      }
    
  •   import java.util.*;
      public class Stacks {
      	static String[] months = { 
      		"January", "February", "March", "April",
      		"May", "June", "July", "August", "September",
      		"October", "November", "December" };
      	public static void main(String[] args) {
      		Stack stk = new Stack();
      		for(int i = 0; i < months.length; i++)
      			stk.push(months[i] + " ");
      		System.out.println("stk = " + stk);
      		System.out.println("popping elements:");
      		while(!stk.empty())
      			System.out.println(stk.pop());
      	}
      }
    
  • 队列

    import java.util.*;
    class TestQueue 
    {
    	public static void main(String[] args) 
    	{
    		Queue q = new Queue();
    		for( int i=0; i<5; i++ )
    			q.enqueue( ""+i );
    		while( ! q.isEmpty() )
    			System.out.println( q.dequeue() );
    	}
    }
    
    class Queue extends LinkedList
    {
    	void enqueue( Object obj ){
    		addLast( obj );
    	}
    	Object dequeue(){
    		return removeFirst();
    	}
    	public boolean isEmpty(){
    		return super.isEmpty();
    	}
    }
    

Set集

两个重要的实现 HashSet及TreeSet
Set中对象不重复:HashCode()不等

Map集

map是键值对的集合

import java.util.*;
class TestMap
{
	public static void main( String[] args){
		//Map<String, String> map = new HashMap<String, String>();
		Map<String, String> map = new TreeMap<String, String>();
		map.put("b", "Brazil");
		map.put("r", "Russia");
		map.put("i", "India");
		map.put("c", "China");
		map.put("k", "South Africa");
		//map.put(new String("c"), "China2");
		//map.put(new String("b"), "Brazil3");

		System.out.println( map.get("c") );

		for( String key : map.keySet() )
			System.out.println( key +":" + map.get(key) );

		for( String value  : map.values() )
			System.out.println( value );

		for( Map.Entry<String,String> entry : map.entrySet() )
			System.out.println( entry.getKey() +":" + entry.getValue() );

		Iterator it = map.entrySet().iterator();
		while(it.hasNext()){
			Map.Entry<String,String> entry = (Map.Entry<String,String>)it.next();
			System.out.println( entry.getKey() +":" + entry.getValue() );
		}
	}
}

排序查找

排序

Arrays类

Arrays.asList(10,7,6,5,9)//可以直接得到一个List对象

Arrays类提供sort()和binarySearch()

// Testing the sorting & searching in Arrays
import java.util.*;

public class TestArraysSort {
  static Random r = new Random();
  static String ssource = 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
    "abcdefghijklmnopqrstuvwxyz";
  static char[] src = ssource.toCharArray();
  // Create a random String
  public static String randString(int length) {
    char[] buf = new char[length];
    int rnd;
    for(int i = 0; i < length; i++) {
      rnd = Math.abs(r.nextInt()) % src.length;
      buf[i] = src[rnd];
    }
    return new String(buf);
  }
  // Create a random array of Strings:
  public static 
  String[] randStrings(int length, int size) {
    String[] s = new String[size];
    for(int i = 0; i < size; i++)
      s[i] = randString(length);
    return s;
  }
  public static void print(byte[] b) {
    for(int i = 0; i < b.length; i++)
      System.out.print(b[i] + " ");
    System.out.println();
  }
  public static void print(String[] s) {
    for(int i = 0; i < s.length; i++)
      System.out.print(s[i] + " ");
    System.out.println();
  }
  public static void main(String[] args) {
    byte[] b = new byte[15];
    r.nextBytes(b); // Fill with random bytes
    print(b);
    Arrays.sort(b);
    print(b);
    int loc = Arrays.binarySearch(b, b[10]);
    System.out.println("Location of " + b[10] +
      " = " + loc);
    // Test String sort & search:
    String[] s = randStrings(4, 10);
    print(s);
    Arrays.sort(s);
    print(s);
    loc = Arrays.binarySearch(s, s[4]);
    System.out.println("Location of " + s[4] +
      " = " + loc);
  }
} 

关于比较

  • 对象是java.lang.Comparable
    实现方法

    public int compareTo(Object obj){
        return this.price - ((Book)obj).price;
    }
    
  • 提供一个java.lang.Comparator
    实现方法
    public int compare(T 01,T o2)

自定义排序

import java.util.*;
class TestCollectionsSort 
{
	public static void main(String[] args) 
	{
		List<Person> school = new ArrayList<Person>();
		school.add( new Person("Li",23));
		school.add( new Person("Wang",28));
		school.add( new Person("Zhang",21));
		school.add( new Person("Tang",19));
		school.add( new Person("Chen",22));
		school.add( new Person("Zhao",22));
		System.out.println( school );
		
		Collections.sort( school, new PersonComparator() );
		System.out.println( school );

		int index = Collections.binarySearch( 
				school, new Person("Li",23), new PersonComparator() );//给他一个比较器
		if( index >=0 ) 
			System.out.println( "Found:" + school.get( index ));
		else
			System.out.println( "Not Found!" );
	}
}

class Person
{
	String name;
	int age;
	public Person( String name, int age){ 
		this.name=name;
		this.age=age;
	}
	public String toString(){
		return name+":"+age;
	}
}

class PersonComparator implements Comparator
{//实现一个自定义排序
	public int compare( Object obj1, Object obj2 ){
		Person p1 = (Person)obj1;
		Person p2 = (Person)obj2;
		if( p1.age > p2.age ) return 1;
		else if(p1.age<p2.age) return -1;
		return p1.name.compareTo( p2.name );
	}
}
import java.util.*;
class TestCollectionsSortByLambda
{
	public static void main(String[] args) 
	{
		List<Person> school = new ArrayList<>();
		school.add( new Person("Li",23));
		school.add( new Person("Wang",28));
		school.add( new Person("Zhang",21));
		school.add( new Person("Tang",19));
		school.add( new Person("Chen",22));
		school.add( new Person("Zhao",22));
		System.out.println( school );
		
		Collections.sort( school, (p1,p2)->p1.age-p2.age );
		System.out.println( school );

		int index = Collections.binarySearch( 
				school, new Person("Li",23), (p1,p2)->p1.age-p2.age );
		if( index >=0 ) 
			System.out.println( "Found:" + school.get( index ));
		else
			System.out.println( "Not Found!" );
	}
}

class Person
{
	String name;
	int age;
	public Person( String name, int age){ 
		this.name=name;
		this.age=age;
	}
	public String toString(){
		return name+":"+age;
	}
}

泛型

使用泛型可以针对不同的类有相同的处理方法

Vector <String> v = new Vector <String> ();
v.addElement("one");
String s = v.elementAt(0);
import java.util.*;

class GenericTreeClass {
	public static void main(String[] args){ 
		TNode<String> t = new TNode<>("Roo");
		t.add("Left"); t.add("Middle"); t.add("Right");
		t.getChild(0).add("aaa");
		t.getChild(0).add("bbb");
		t.traverse();
	}
}

class TNode<T>
{
  private T value;
  private ArrayList<TNode<T>> children = new ArrayList<>();

  TNode(T v) { this.value = v; } 
  public T getValue() { return this.value; } 
  public void add(T v) {
    TNode<T> child = new TNode<>(v);
    this.children.add(child);
  }
  public TNode<T> getChild(int i) {
    if ((i < 0) || (i > this.children.size())) return null;
    return (TNode<T>)this.children.get(i);
  }

  public void traverse() {
    System.out.println(this.value);
    for (TNode child : this.children)
      child.traverse();
  }

import java.util.*;

class GenericMethod {
	public static void main(String[] args){ 
		Date date = BeanUtil.<Date>getInstance("java.util.Date");
		System.out.println(date);
	}
}

class BeanUtil{
	public static <T> T getInstance( String clzName ){
		try
		{
			Class c = Class.forName(clzName);
			return (T) c.newInstance();
		}
		catch (ClassNotFoundException ex){}
		catch (InstantiationException ex){}
		catch (IllegalAccessException ex){}
		return null;
	}
} 

对类型限定

  • 使用?
    Collections的reverse方法
    reverse(List <?> list)
  • 使用extends
    Set的addAll方法
    addAll(Collection <? Extends E> col)
  • 使用super
    如Collections的fill方法
    fill(List <? Super T) list, T obj)

多线程

进程:一个程序的执行
线程:程序中单个顺序的流控制
一个程序中可以含有多个线程

创建线程

  1. 通过继承Thread类创建线程

    class MyThread extends Thread{
        public void run(){
            for(int i=0;i<100;i++){
                System.out.print(" "+i);
            }
        }
    }
    
  2. 通过向Thread()构造方法传递Runnable对象来创建线程

    class MyTask implements Runnable{
        public void run(){
            
        }
    }
    
    Thread thread = new Thread(mytask);
    thread.start();
    
  3. 使用匿名类

    new Thread(){
        public void run(){
            for(int i=0;i<10;i++){
                System.out.print(i);
            }
        }
    }
    
  4. 使用Lambda表达式
    new Thread( ()-> {...}).start();

使用多线程

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test {
    public static void main(String args[]) {
        Counter c1 = new Counter(1);
        Thread t1 = new Thread(c1);
        Thread t2 = new Thread(c1);
        Thread t3 = new Thread(c1);
        Counter c2 = new Counter(2);
        Thread t4 = new Thread(c2);
        Thread t5 = new Thread(c2);
        Thread t6 = new Thread(c2);
        TimeDisplay timer = new TimeDisplay();
        Thread t7 = new Thread(timer);
        t1.start();
        t2.start();
        t4.start();
        t5.start();
    }
}

class Counter implements Runnable {
    int id;

    Counter(int id) {
        this.id = id;
    }

    public void run() {
        int i = 0;
        while (i++ <= 10) {
            System.out.println("ID: " + id + " No. " + i);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
            }
        }
    }
}

class TimeDisplay implements Runnable {
    public void run() {
        int i = 0;
        while (i++ <= 3) {
            System.out.println(new SimpleDateFormat().format(new Date()));
            try {
                Thread.sleep(40);
            } catch (InterruptedException e) {
            }
        }
    }
}
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JApplet
{
    MovingShape [] shapes;

    public void init()
    {
        setLayout(null);
        setSize(426,266);

        shapes = new MovingShape[ 10 ];
        for( int i=0; i<shapes.length; i++ ){
            shapes[i] = new MovingShape(this);
            shapes[i].start();
        }

    }

    public void destroy()
    {
        for( int i=0; i<shapes.length; i++ )
            shapes[i].stopped =true;
        super.destroy();
    }

    public static void main(String [] args) //加入main,使之能当Application应用
    {
        Frame f = new Frame();
        f.setSize(450,300 );
        Test p = new Test();
        f.add ( p );
        f.setVisible( true );
        p.init();
        p.start();
        f.addWindowListener( new WindowAdapter(){
            public void windowClosing(WindowEvent e){ System.exit(0); }
        });
    }
}


class MovingShape extends Thread
{

    private int size=100;
    private int speed=10;
    private Color color;
    private int type;
    private int x,y,w,h,dx,dy;
    protected java.awt.Component app;

    public boolean stopped;

    MovingShape( java.awt.Component app )
    {
        this.app = app;
        x = (int)(Math.random() * app.getSize().width);
        y = (int)(Math.random() * app.getSize().height);
        w = (int)(Math.random() * size );
        h = (int)(Math.random() * size );
        dx = (int)(Math.random() * speed );
        dy = (int)(Math.random() * speed );
        color = new Color (
                (int)(Math.random()*128+128),
                (int)(Math.random()*128+128),
                (int)(Math.random()*128+128) );
        type = (int)(Math.random() * 3 );

    }

    public void run()
    {
        while( true ){
            if( stopped ) break;

            //draw();
            SwingUtilities.invokeLater(
                    new Runnable(){
                        public void run(){
                            draw();
                        }
                    } );

            try{ Thread.sleep(130); } catch( InterruptedException e ){}
        }
    }

    void draw(){
        x += dx;
        y += dy;
        if( x<0 || x+w>app.getSize().width ) dx = -dx;
        if( y<0 || y+h>app.getSize().height) dy = -dy;
        Graphics g = app.getGraphics();

        switch( type ){

            case 0:
                g.setColor(color);
                g.fillRect( x,y,w,h );
                g.setColor( Color.black );
                g.drawRect( x,y,w,h );
                break;
            case 1:
                g.setColor(color);
                g.fillOval( x,y,w,h );
                g.setColor( Color.black );
                g.drawOval( x,y,w,h );
                break;
            case 2:
                g.setColor(color);
                g.fillRoundRect( x,y,w,h,w/5,h/5);
                g.setColor( Color.black );
                g.drawRoundRect( x,y,w,h,w/5,h/5 );
                break;
        }
    }
}

线程控制

  • 启动
    start()

  • 结束
    设定一个标记变量,以结束相应的循环

  • 暂时阻止线程执行

    try{Thread.sleep(1000);}catch(InterruptedException e){}
    
  • 设定线程优先级
    setPriority(int priority)方法
    MIN_PRIORITY, MAX_PRIORITY, NORM_PRIORITY

后台线程

  • 一类是普通线程(非Daemon线程)
    若存在非Daemon线程,则程序不会结束
  • 一类是Daemon线程(守护线程,后台线程)
    普通线程结束了,则后台线程自动终止

使用setDaemon(true);

例如垃圾回收线程是后台线程

import java.util.*;
public class TestThreadDaemon {
	public static void main(String args[]) {
		Thread t = new MyThread();
		t.setDaemon(true);
		t.start();

		System.out.println( "Main------" + new Date());
		try{ Thread.sleep(500); } catch(InterruptedException ex){}
		System.out.println("Main End");
	}
}

class MyThread extends Thread {
	public void run() {
		for(int i=0; i<10; i++ ){
			System.out.println(  i + "------" + new Date());
			try{ Thread.sleep(100); } catch(InterruptedException ex){}
		}
	}
}

线程同步

class TestThreadCount 
{
	public static int cnt=0;
	public static void main(String[] args) 
	{
		final int NUM=50000;
		Thread [] threads = new Thread[NUM];
		for(int i=0; i<NUM; i++){
			threads[i] = new Thread(){
				public void run(){ 
					cnt++; 
				}
			};
		}
		for(int i=0; i<NUM; i++) threads[i].start();
		try{ Thread.sleep(3000); } catch(InterruptedException ex){}
		System.out.printf("%d %b\n", cnt, cnt==NUM);
	}
}

互斥锁

保证共享数据操作的完整性
每个对象都对应于一个monitor监视器,他上面一个成为互斥锁的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象
关键字synchronized用来与对象的互斥锁联系

synchronized用法:

  • 对代码片段:
    synchronized(对象){…}
  • 对某个方法
    Synchronized 放在方法声明中
    public synchronized void push(char c){}
    相当于对synchronized(this)表示整个方法为同步方法
class SyncCounter2
{
	public static void main(String[] args){ 
		Num num = new Num();
		Thread counter1 = new Counter(num);
		Thread counter2 = new Counter(num);
		for( int i=0; i<10; i++ ){
			num.testEquals();
			try{							           
				Thread.sleep(100);
			}catch(InterruptedException e){
			}
		}
	}
}

class Num
{
	private int x=0;
	private int y=0;
	synchronized void increase(){ 
		x++; 
		y++; 
	}
	synchronized boolean testEquals(){
		boolean ok = (x==y);
		System.out.println( x + "," + y +" :" + ok);
		return ok;
	}
}

class Counter extends Thread
{
	private Num num;
	Counter( Num num ){
		this.num = num;
		this.setDaemon(true);
		this.setPriority(MIN_PRIORITY);
		this.start();
	}
	public void run(){
		while(true){
			num.increase();
		}
	}
}

使用wait()方法可以释放对象锁
使用notify()或notifyAll()可以让等待的一个或所有线程进入就绪状态

class Producer extends Thread {
	private CubbyHole cubbyhole;
	private int number;

	public Producer(CubbyHole c, int number) {
		cubbyhole = c;
		this.number = number;
	}

	public void run() {
		for (int i = 0; i <10; i++) {
			cubbyhole.put(i);
			//System.out.println("Producer #" + this.number + " put: " + i);
			//try {
			//	sleep((int)(Math.random() * 100));
			//} catch (InterruptedException e) {
			//}
		}
	}
}

class Consumer extends Thread {
	private CubbyHole cubbyhole;
	private int number;

	public Consumer(CubbyHole c, int number) {
		cubbyhole = c;
		this.number = number;
	}

	public void run() {
		int value = 0;
		for (int i = 0; i <10; i++) {
			value = cubbyhole.get();
			//System.out.println("Consumer #" + this.number + " got: " + value);
		}
	}
}

class CubbyHole1
{
	private int seq;
	public synchronized int get() {
		return seq;
	}
	public synchronized void put(int value) {
		seq = value;
	}
}

class CubbyHole2
{
	private int seq;
	private boolean available = false;

	public synchronized int get() {
		while (available == false) ; //dead locked !!!
		return seq;
	}
	public synchronized void put(int value) {
		while (available == true) ;
		seq = value;
		available = true;
	}
}

class CubbyHole3 {
	private int seq;
	private boolean available = false;

	public synchronized int get() {
		while (available == false) {
			try {
				wait(); // waits for notify() call from Producer
			} catch (InterruptedException e) {
			}
		}
		available = false;
		notify();
		return seq;
	}

	public synchronized void put(int value) {
		while (available == true) {
			try {
				wait(); // waits for notify() call from consumer
			} catch (InterruptedException e) {
			}
		}
		seq = value;
		available = true;
		notify();
	}
}


class CubbyHole {
	private int data[] = new int[3];
	private int index = 0;

	public synchronized int get() {
		while (index <= 0) {
			try {
				wait(); // waits for notify() call from Producer
			} catch (InterruptedException e) {
			}
		}
		index --;
		int value = data[index];
		System.out.println("Consumer " +  " got: " + data[index]);
		notify();
		return value;
	}

	public synchronized void put(int value) {
		while (index >= data.length) {
			try {
				wait(); // waits for notify() call from consumer
			} catch (InterruptedException e) {
			}
		}
		System.out.println("Producer " + " put: " + value);
		data[index] = value;
		index ++;
		notify();
	}
}

class ProducerConsumerStack {
	public static void main(String args[]) {
		CubbyHole c = new CubbyHole();
		Producer p1 = new Producer(c, 1);
		Consumer c1 = new Consumer(c, 1);
		p1.start();
		c1.start();
	} 
}

也有可能造成死锁互相等待的情况

class DeadLockDemo{
	class Worker
	{
		int id;
		public Worker(int id){ this.id=id; }
		synchronized void doTaskWithCooperator(Worker other){
			try{ Thread.sleep(500); } catch(Exception e){}
			synchronized(other){
				System.out.println("doing" + id);
			}
		}
	}
	void test(){
		Worker w1 = new Worker(1);
		Worker w2 = new Worker(2);
        Thread td1 = new Thread(){
			public void run(){ 
				w1.doTaskWithCooperator(w2);
			}
		};
        Thread td2 = new Thread(){
			public void run(){ 
				w2.doTaskWithCooperator(w1);
			}
		};
		td1.start();
		td2.start();
    }
	public static void main(String[] args) {
		new DeadLockDemo().test();
	}
}

并发API

java.util.concurrent包

原子变量

Java.util.concurrent.atomic
AtomicInteger类
getAndIncrement()方法

import java.util.concurrent.atomic.AtomicInteger ;
class AtomicIntegerDemo
{
	public static AtomicInteger cnt = new AtomicInteger(0);
	public static void main(String[] args) 
	{
		final int NUM=10000;
		Thread [] threads = new Thread[NUM];
		for(int i=0; i<NUM; i++){
			threads[i] = new Thread(){
				public void run(){ 
					cnt.getAndIncrement(); 
				}
			};
		}
		for(int i=0; i<NUM; i++) threads[i].start();
		try{ Thread.sleep(3000); } catch(InterruptedException ex){}
		System.out.printf("%d %b\n", cnt.get(), cnt.get()==NUM);
	}
}

线程池

线程池相关类
ExecutorService接口,ThreadPoolExecutor类
Executors工具类

ExecutorService pool = Executors.newCachedThreadPool();
使用其execute( Runnable r)方法

import java.util.concurrent.*;

class ThreadPoolDemo 
{
	public static void main(String[] args) 
	{
		ExecutorService pool = Executors.newCachedThreadPool();
		MyTask t1 = new MyTask(5);
		MyTask t2 = new MyTask(7);
		MyTask t3 = new MyTask(8);
		pool.execute(t1);
		pool.execute(t2);
		pool.execute(t3);
		pool.shutdown();
	}
}
class MyTask implements Runnable
{
	int n=10;
	public MyTask(int n){ this.n=n;}
	public void run(){
		for(int i=0;i<n; i++)System.out.print(i);
	}
}

组件

Swing组件

JComponent是非顶层容器,都是容器,都有add子组件

实现界面的步骤

  • 创建组件
  • 指定布局
  • 响应事件
import javax.swing.*;
import java.awt.*;

public class TestJFrame extends JFrame
{
    private JLabel lbl;

    public TestJFrame()
    {
        super("Test JFrame");

        lbl = new JLabel("Hello Swing");
        //add(lbl);
        getContentPane().add(lbl);

        setSize(300, 200);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public static void main(String[] args)
    {
        new TestJFrame().setVisible(true);
    }
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class JButtonDemo extends JFrame {
	JButton b1 = new JButton("JButton 1");
	JButton b2 = new JButton("JButton 2");
	JTextField t = new JTextField(20);
	public JButtonDemo() {

		b1.setToolTipText("Press Button will show msg");
		b1.setIcon( new ImageIcon( "cupHJbutton.gif") );

		getContentPane().setLayout( new FlowLayout() );
		getContentPane().add(b1);
		getContentPane().add(b2);
		getContentPane().add(t);

		setSize(400,300);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

		ActionListener al = new ActionListener() {
			public void actionPerformed(ActionEvent e){
				String name = 
					((JButton)e.getSource()).getText();
				t.setText(name + " Pressed");
			}
		};
		b1.addActionListener(al);
		b2.addActionListener(al);
	}

	public static void main(String args[]) {
		new JButtonDemo().setVisible(true);
	}
}

事件监听器

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestActionEvent  {
    public static void main(String args[]) {
		JFrame f = new JFrame("Test");
		JButton btn = new JButton("Press Me!");
		f.add(btn);
		
		ActionListener al = new MyListener();
		btn.addActionListener(al);
		
		f.setSize(300, 120);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setVisible(true);
    }
}

class MyListener implements ActionListener{
	@Override
	public void actionPerformed(ActionEvent e) {
        System.out.println("a button has been pressed");    
    }
}

事件监听器是一些事件的接口
接口中含有相关的方法:
MouseMotionListener是对鼠标移动事件的处理的接口,它含有两个重要的方法:
void mouseDragged(MouseEvent e);//处理鼠标拖动的方法
void mouseMoved(MoudeEvent e);//处理鼠标移动方法

事件类中包含有事件相关的信息:

  1. 事件源(即产生事件的组件)
    getSource()
    得到的Object可以强制转换成相应的类型
  2. 事件的具体情况
    如MouseEvent的getX(),getY()方法得到鼠标的坐标
    KeyEvent的getKeyChar()得到当前的字符

事件适配器

简化实现Listener

注册事件监听器

add xxxx Listener

监听器实现方法

  • implements xxxxListener
  • Extends xxxAdapter
    其中Adapter是Listener的默认实现,每个方法的方法体为空
    Adapter可以只Override其中重要的方法
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Java笔记是由北京大学青鸟教育推出的一款专门针对Java语言的学习工具。它以全面、系统、实践为特点,通过详细的代码示例和清晰的讲解,帮助学习者全面掌握Java编程语言。 Java笔记采用了线上与线下相结合的学习模式。学员可以通过手机、平板电脑、电脑等设备在线学习,还可以在学习过程中随时记录自己的学习笔记。同时,北大青鸟还为学员提供线下实践环境,学员可以在实验室里亲自动手实践所学知识,加深理解和应用。 Java笔记的内容非常全面,包括了Java语言的基本语法、面向对象编程、异常处理、流操作、多线程、数据库操作等众多知识点。除了理论知识,Java笔记还提供了大量的实例代码,可供学员参考和模仿。这样的学习方式既帮助学员理解Java的基本概念,又能让他们运用所学知识解决实际问题。 与此同时,Java笔记还注重学员的互动交流。在学习过程中,学员可以利用笔记功能记录学习心得和疑惑,还可以在论坛上与其他学员进行讨论和交流。这种互动形式既能促进学员之间的学习互助,也能更好地帮助学员理解和应用所学知识。 总之,Java笔记是北大青鸟推出的一款专注于Java语言学习的工具,通过系统的课程设置、丰富的实例代码和互动交流的方式,帮助学员全面掌握Java编程知识,提升编程能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhj12399

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值