JAVA学习笔记——基础语法

Java_1.8_API

Java Application初步

  • Java的源文件后缀是**.java**。类**.class**是源文件的基本组成部分
  • 一个源文件中最多只能有一个public类,且其名字与文件名相同
  • Java Application的执行入口是main()方法。其的书写方法是:public static void main(String args[]){...}

Java变量

按被声明的位置划分

  • 局部变量:方法或语句块内部定义的变量(包括形参),局部变量在栈stack里分配内存。
  • 成员变量:方法外部、类的内部定义的变量,非静态成员变量在堆heap里分配内存,静态成员变量在数据区data segment里分配内存。
  • 注意:类外面(与类对应的大括号外面)不能有变量的声明

按所属的数据类型划分

  • 基本数据类型变量
  • 引用数据类型变量
  • 变量若没有初始化,则默认为0,false,null

基本数据类型变量

  • 布尔型boolean:只允许取true和false,不能用0和非0代替
  • 整型byte,short,int,long(Java里没有无符号整型):整型常量默认为int;声明long型常量后必须加'l'或'L',否则会出错
  • 浮点型float,double:浮点型常量默认为double;声明float型常量需加'f'或'F',否则会出错

引用数据类型变量

基础数据类型以外的所有类型都是引用数据类型

  • 引用可以看成是C语言中的指针
  • 引用指向的值全都放在堆内存里(即new出来的值都放在堆内存里),若声明了一个引用但没有new,则其值为null,即不指向任何值

数组

*数组不是基本类型,是引用类型,所以数组是存放在堆heap中的

  • Java中声明数组的时候不能指定长度,如下
int i[5];//非法
int s[]或者int[] s;//合法
s = new int [5];//此时堆空间分配五个空间
复制代码
  • s.length为数组s的长度
  • 如果数组存放的是引用型数据,则需像下面这样使用
/*
动态初始化
Data days[];
days = new days[3];
days[0] = new Data(2018, 4, 2);
*/
//或者静态初始化
Data days[] = {
    new Data(2018, 4, 2);
    new Data(2018, 4, 3);
    new Data(2018, 4, 4);
}
//或者
int[] s = new int[9];
复制代码

二维数组

//多维数组的初始化时从高维到低维的
int a[][] = new int[3][];
a[0] = new int[2];
a[1] = new int[4];
a[2] = new int[3];

/*
错误示范
int t1[][] = new int[][3];
*/

//静态初始化
int a2[][] = { {1,2}, {4,1,5}, {2,5,4,1,5,2} };

/*
错误示范
int t2[3][2] = { {1,2}, {3,4}, {5,6} };
*/

//动态初始化
int a3[][] = new int[3][5];
复制代码

==需要注意的是,java中的多维数组的内存并不是像c语言中的多维数组一样连续存放的,只有单一维度才是连续存放的。==

数组的复制

利用java.lang.System中的arraycopy可以实现数组的复制

//调用方法
System.arraycopy(源数组, int 复制起点, 目标数组, int 复制起点, 复制元素个数)
复制代码

变量类型的强制转换

例如要将一个字符型变量i强制转化为double型,则

double d = Double.parseDouble(i);
复制代码

运算符

  • 逻辑运算符:!-逻辑非,&-逻辑与,|-逻辑或,^-逻辑异或(两者相同时为假),&&-短路与,||-短路或(与C语言的与或相同)
  • 赋值运算符=:可以将整型常量赋值给byte,short,char等类型变量,只要不超出范围即可
  • 字符串连接符+:'+'除了可以用来做算术加法,还可以对字符串进行连接操作。==PS:'+'运算符两侧操作数只要有一个是String类型,系统就会自动将另一个操作数转化为字符串然后进行连接。==

方法

格式:[修饰符1 修饰符2 ...] 返回值类型 方法名(形式参数列表) { Java 语句; ... ... } 调用格式:对象名.方法名(实参列表) return语句结束方法的执行

方法的重载Overload

一个类中可以定义多个返回类型相同,名字相同,但参数个数类型不相同的方法,例如:

class Max {
    void max(int a, int b) {
        System.out.println( a > b ? a : b );
    }
    
    void max(double a, double b) {
        System.out.println ( a > b ? a : b );
    }
    
    void max(char a, char b, char c) {
        ...
    }
    
    /*
    int max(int a, int b) {
        return a > b ? a : b ;
    }
    这个是错的,因为返回类型是int不是void
    */
}
复制代码

调用Max类中的max方法时,编译器会通过判断max中的参数列来判断调用哪一个max方法。

方法的重写Overwrite/Override

  • 在子类中可以根据需要对从基类继承来的方法进行重写。
  • ==重写的方法必须与原方法具有相同的名称,返回类型,参数列表。== 十分容易在这里出错,所以每次重写时直接复制父类的方法声明。
  • 重写的方法不能使用比原方法更严格的访问权限。

异常处理

try {
    //可能出错的代码
} catch(SomeException1 e) {
    //出现异常SomeException1时的处理
} catch(SomeException2 e) {
    // e可以理解为SomeException2类型的形参,用来当异常出现时接收该异常
} finally {
    //无论出不出错都会执行的代码
}
复制代码

==当异常出现时,程序会立刻停止当前的流程,根据异常的类型去执行相应的catch代码,然后直接跳去执行finally段代码。==

通常在finally语句中执行资源清楚工作,如:

  • 关闭打开的文件
  • 删除临时文件
  • ······

Java中定义的异常类有如下分类:

graph TD
A[Throwable]-->B(Error)
A[Throwable]-->C(Exception)
C(Exception)-->D(RuntimeException)
C(Exception)-->E(其他)
复制代码
  • 其中Throwable类是所有异常类的基类,只要是继承它的类,就可以被抛出
  • Error类为系统的内部错误,无法干涉,处理不了的错误
  • Exception类是可以人为处理的异常,
  • RuntimeException类是程序在运行时发生的异常,经常出现,这种异常,可以catch,也可以不catch,因为这类异常出现十分频繁
  • 除RuntimeException、Error外的其他异常,必须catch

Java在处理异常的时候,调用printStackTrace方法可以将异常一层一层地打印出来(与python类似)

自定义异常

步骤:

  1. 通过继承Exception类声明该类为异常类,格式如下
class MyException extends Exception {
    public MyException(String message) {
        super(message);
        //message为错误的相关信息
    }
}
复制代码
  1. 在需要抛出自定义异常的时候,生成并抛出,如下
public void test(int i) {
    if(i<0) {
    throws new MyException("i不能小于0");
    }
}
复制代码

注意事项

  • catch异常的时候,如果catch了Exception,那么这个catch后面的其他catch代码段就失效了,因为Exception是所有可以catch的Exception的基类,所以,catch的异常类越细越好。==即先抛小的,再抛大的。==
  • 如果一个方法可能会抛出某种异常,但是你又不想在这个方法内部处理它,那么可以在声明时使用throws关键字,然后在调用该方法时再用try,catch来捕获异常,如下
void f() throws IOException {
    ...
    //该方法可能抛出IOException
}

public static void main(String argsp[]) {
    try {
        f();
    } catch (IOException e) {
        
    }
}
复制代码
  • 当一个方法抛出异常后,剩余下来的语句不会被执行
  • 重写有抛出异常的方法时,必须抛出相同类型的异常或者不抛出

关键字

this 关键字

类似于Python中的self,this指向调用某方法的对象本身,即其值为当前对象的引用

public class Leaf {
    int i = 0;
    //Leaf方法中的this.i指的是对象的i,即上面声明的i
    Leaf(int i) {
        this.i = i;
    }
    
    Leaf increament() {
        i++;
        return this;
        //返回的是Leaf的引用
    }
    
    void print() {
        System.out.println("i = " + i);
    }
    
    public static void main(String args[]) {
        Leaf leaf = new Leaf(100);
        leaf.increament().increament().print();
    }
    //输出 i = 102
}
复制代码

补充:在一个类中,如果使用this(argument_list)则代表调用了该类中的某个构造方法,具体是哪个构造方法由参数列argument_list决定

static 关键字

  • 在类中,用static声明的成员变量称为静态成员变量。
  • 用static声明的方法为静态方法,在调用该方法时不会将对象的引用(this)传递给它,所以在静态方法中不能访问非静态成员。(类似于Python中的staticmethod)
  • 可以通过对象.静态成员或者类名.静态成员来访问静态成员。

package 关键字

为便于管理大型软件系统中数目众多的类,解决类的命名冲突问题,Java引入包(package)机制,提供类的多重类命名空间

  • 若想将一个类放入某个包中,在这个类的源文件的第一行写:
package pkg1.pkg2.pkg3;
复制代码
  • 注意
  1. 必须保证该类的.class文件放在正确的目录下即pkg1/pkg2/pkg3...
  2. 将该类的源文件.java移至其他目录下,否则该类的源文件可能会产生影响
  3. class文件的最上层包的父目录必须位于classpath下,即com上一级目录在classpath下
  4. 用cmd执行的时候也需要写全包名
打包jar包

在cmd里定位到想打包的包的com的上一级目录,然后输入命令

jar -cvf 名字.jar *.*

生成的jar包就和com在同一个目录下,此时再将.../com/名字.jar 加入到classpath里就可以使用jar包里面的内容了

import 关键字

  • 想访问某一个包内的类可以:
import pkg1.pkg2....具体类名;
//或者
import pkg1.pkg2....*;
//这种方法可以访问包内所有的类
复制代码

super 关键字

  • 利用super.fatherMethod()可以引用基类中的方法

final 关键字

被final关键字修饰的变量、形参无法被改变,被修饰的方法无法被重写,被修饰的类无法被继承。类似于C语言中的const

常用类

String类

String类代表==不可变==的字符序列

  • 因为String类不可变,所以对该类的对象进行操作的时候,效率会比较低
StringBuffer类

StringBuffer代表==可变==的字符序列

基础类型包装类

不同于基础类型的是,其包装类是存放在堆heap内存中的

Math类

该类提供了一系列静态方法用于科学计算,其方法的参数和返回值的类型一般为double

File类

代表系统文件名(路径或文件名),而不是文件 *File中的静态属性String separator存储了当前系统的分隔符,windows下是'',unix下是'/'。==然而不论是在windows还是UNIX,都写'/'就可以。==

枚举类型Enum类
//使用方法
//括号内为该枚举类型的可能取值
public enum classname (a, b, ..) {
    //变量test只能取括号内的值
    classname test = classname.a;
    switch(test) {
        case a:...;
        case b:...;
    }
}
复制代码
//构造方法
public File(String pathname)
//以pathname为路径创建一个File对象,如果pathname是相对路径,
复制代码

类的继承Inherit与权限控制

//继承的语法
//========NewClass继承了SuperClass内的所有成员========
class NewClass extends SuperClass {...}
复制代码
  • 通过继承,子类拥有了**基类(superclass)**或者说父类的所有成员(即成员变量和方法)
  • Java只允许单继承不允许多继承

访问控制--Java权限修饰符

Java权限修饰符置于类的成员定义前,用来限制其他对象对该类成员的访问权限。

  • private:private成员只能在类的内部访问。
  • default:default成员可以在类的内部以及同一个包内访问。
  • protected:protected成员可以在类的内部、同一个包内、子类内访问。
  • public:public成员在任何地方都可以访问。

PS:class只可以用public和default修饰,并且,被default修饰的class只可以在同一个包内部的类访问

构造方法

类中有一个与类同名的方法,叫做构造方法(无返回类型),如:

public class Person {
    int id;
    int age;
    Person(int _id, int _age) {
        id = _id;
        age = _age;
    }
}
复制代码

上例中,Person类中的同名方法Person(int _id, int _age)称为构造方法,此方法是在new一个新的Person类是调用的,如:

Person Mike = new Person(10086, 20)
复制代码

上述过程定义Mike时调用了Person类中的构造方法

继承中的构造方法

  • ==子类的构造过程中必须调用基类的构造方法。==
  • 子类在其构造方法中使用super(argument_list)调用基类的构造方法(++调用哪个构造方法由argument_list决定++),并且必须写在子类构造方法的第一行。
  • 也可以使用this(argument_list)调用本类其他构造方法。
  • 如果子类中没有显式调用基类的构造方法,则默认调用基类中无参构造方法,若基类中没有无参构造方法,则编译出错。

object类

  • object类是所有Java类的根基类
  • 如果类的声明未使用extends声明其基类,则默认object类为其基类
  • object类中有一个toString方法,该方法默认返回调用它的对象的类的名字,通常情况下要将toString方法重写,然后返回当前对象的有关信息。
System.out.println("Person = " + p1);
//当进行String与其他数据类型的连接操作时,默认调用toString方法,即上面的代码等价于
//System.out.println("Person = " + p1.toString)
复制代码
  • objcet类中的equals方法需要自己重新定义比较方式。字符串与字符串使用equals方法,默认判断两个字符串是否相同

对象转型casting

  • 一个基类的引用类型可以指向其子类的对象,但这个引用不能访问子类中新增加的成员(属性和方法)
  • 可以通过使用 a instanceof b 来判断a所指向的对象是否属于b类或者b的子类
  • 子类的对象可以当作基类的对象来使用,称为向上转型upcasting,反之称为向下转型downcasting
class Animal {
    public String name;
    Animal(String name) {
        this.name = name;
    }
}

class Cat {
    public String eyesColor;
    Cat(String name, String eyesColor) {
        super(name);
        this.eyesColor = eyesColor;
    }
}

class Dog {
    public String furColor;
    Dog(String name, String furColor) {
        super(name);
        this.furColor = furColor;
    }
}

public class Test {
    public static void main() {
        Test t = new Test();
        //定义t可以使t访问方法f
        Animal a = new Animal("animal");
        Cat c = new Cat("cat", "bule");
        Dog d = new Dog("dog", "black");
        
        t.f(a);
        t.f(c);
        t.f(d);
        //因为c和d都是Animal的子类对象,所以可以作为参数Animal x传入方法f
    }
    
    public void f(Animal x) {
        System.out.println("name = " + x.name);
        if(x instanceof Cat) {
            System.out.println("eyesColor = " + x.eyesColor);
        }
        else if(x instanceof Dog) {
            
            System.out.println("furColor = " + x.furColor);
        }
    }
}
复制代码

多态Polymoph(也叫动态绑定、迟绑定)———面向对象的核心

动态绑定是指,在程序执行过程期间(非编译期间),判断所引用对象的实际类型,根据其实际类型调用对应的方法。

多态存在的必要条件

  • 要有继承
  • 要有重写
  • 父类引用指向子类对象

满足以上条件后,当调用父类中被重写的方法时,会自动改为调用子类中对应的方法

抽象类

被abstract关键字修饰的类或方法叫做抽象类或抽象方法。

  • 抽象类不能被实例化。(即这个类是不完整的,需要声明它的子类,并由子类来完善它自己)抽象类必须被继承。
  • 抽象方法只需要声明,不需要实现。(即只需要声明有这样的一个方法就行,具体怎么实现,交给子类去重写)抽象方法必须被重写。

抽象类存在的意义:抽象类就像一个未完成的模型,它提供了该类所必须的某些成员与属性。

抽象方法存在的意义:这个方法是每个子类都会有的,但具体实现因类而异,所以它提供一个空的模板,想要怎么重写是子类的事。

接口 interface

接口可以看成是一中特殊的抽象类,它里面只有常量(即public static final修饰的变量)并且默认为常量,和抽象方法的定义(没有实现),并且这些方法必须用public修饰,例如:

public interface Runner {
    public static final int id = 1;
    //方法不需要abstract修饰
    public void run();
    public void stop();
}
复制代码
  • 一个接口可以继承另一个接口,并添加新的属性与方法,但不可以继承类
  • 接口与实现类之间存在多态性,例如:
//student,teacher类都实现了painter(内含方法paint,eat),singer接口(内含方法sing,sleep)
public class Test {
    public static void main() {
        Singer s1 = new Student("le");
        s1.sing();
        s1.sleep();
        //此时s1为接口singer类型的引用,但当s1调用sing和sleep方法的时候,调用的却是Student中sing,sleep方法的具体实现
        Singer s2 = new Teacher("steven");
        s2.sing();
        s2.sleep();
        //类似地,s2调用的是Teacher中sing,sleep方法的具体实现。但要注意的是,s1,s2都只能调用在Singer接口中出现过的方法
        Painter p1 = (Painter)s2;
        p1.paint();
        p1.eat();
        //通过强制类型转换,现在p1可以调用s2中paint,eat方法的具体实现,但是不能调用其他没有在Painter接口中出现过的方法
    }
}
复制代码
  • 类使用implements关键字来实现接口,例如
class A extends B implements C, D, E {...}
复制代码

容器API

容器API类图结构如下:

graph BT
A[HashSet]-->B[interface Set]
C[LinkedList]-->D[interface List]
E[ArrayList]-->D
B-->F[interface Collection]
D-->F
G[HashMap]-->H[interface Map]
复制代码
Collection接口
  • Collection接口定义了存取一组对象的方法,其子接口Set,List分别定义了存储方式。
    • Set中的数据对象没有顺序且不可以重复。
    • List中的数据对象有顺序且可以重复。

注意,collection中只能存放对象

  • 使用Collection接口的remove,contains等方法的时候,需要比较两个对象是否相等,这涉及到了equals和hashcode方法。对于自定义的类型,需要重写equals和hashcode方法来定义对象相等的规则。(相等的对象必须有相同的hashcode)
Set接口

Set接口实现了Collection接口,但是没有新增额外的方法,且实现Set接口的容器类中的元素是没有顺序且不重复的

  • Java中提供的Set容器类有HashSet,TreeSet等。
List接口
  • 实现List接口的容器类中的元素是可重复且有序的。
  • List容器中的每个元素都对应有一个整型序号记录该元素的位置,可以根据序号存取容器中的元素。
  • Java中提供 的List容器类有ArrayList,LinkedList等。
Map接口
  • Map接口定义了存储“键(key)——值(value)映射对”的方法。
  • 实现Map接口的容器类有HashMap、TreeMap等。
  • 键值是Map实现类的对象的标识,所以键值不能重复。
  • Map中的key和value都只能是对象,不能是其他的。
Iterator接口
  • 所有实现了Collection接口的容器类都有一个Iterator方法用以返回一个实现了Iterator接口的对象。
  • Iterator对象称为遍历器,用以方便地实现对容器内元素的遍历操作。
  • Iterator接口定义了如下方法
    • boolean hasNext(); //判断游标右边是否有元素
    • Object next();//返回游标右边的元素并将游标移动到下一个位置
    • void remove();//删除游标左边的元素,在执行完next之后该操作只能执行一次(因为Iterator只能进行next操作而没有指向上一个元素的操作)
    • Iterator对象的remove方法是迭代过程中删除元素唯一安全的方法
如何选择数据结构

Arrayd读快改慢、Linked改快读慢、Hash两者之间

对equals方法和hashcode方法的理解
  • override后的equals方法应该通过比较两个对象中的内容来确定两个对象是否相等。
  • override后的hashcode方法通过特定的计算方法来计算对象中的hashcode的值。
  • 注意:如果hashcode的值会因对象属性的改变而改变,那么则需要十分小心。最好避免这种情况。
  • 重写后的equals和hashcode方法应该遵守:如果两个对象equals,hashcode的值一定相等;如果两个对象的hashcode相等,它们不一定equals。
  • 判断两个对象是否相等可以:先比较hashcode的值,如果不相等,那么两个对象一定不相等;如果相等,再调用equals方法,如果两个对象equals,那么这两个对象才相等。
Auto-boxing和unboxing

例子

机制

泛型Generic

注意:
  • 泛型只在编译阶段有效,下面代码说明,泛型类型实际上还是原来对象所属的类型。
List stringArrayList = new ArrayList();
List integerArrayList = new ArrayList();

Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();

if(classStringArrayList.equals(classIntegerArrayList)){
    Log.d("泛型测试","类型相同");
}//输出 D/泛型测试:类型相同
复制代码

流Stream(输入与输出是从程序的角度来讲的)

输入流和输出流

Java所提供的所有流类型都位于java.io包内,且都分别继承以下4个抽象类。

字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
InputStream
  • 继承自InputStream的流都是用于向程序中输入数据的,单位为字节(8bit)。
  • 基本方法
    • int read() throws IOException;//读取一个字节并以整数(0-255)形式返回
    • int read(byte[] buffer) throws IOException;//读取一系列字节存储于一个数组buffer,返回读取字节的个数
    • int read(byte[] buffer, int offset, int length);//从offset开始读取length个字节
    • void close() throws IOException//关闭流,释放资源
OutputStream
  • 继承自OutputStream的流都是用于从程序中输出数据的,单位为字节。
  • 基本方法
    • void read()
    • void read(byte[] buffer)
    • void read(byte[] buffer, int offset, int length)
    • void close()
    • void flush();//将输出流中缓冲的数据全部写到目的地,用于close之前,防止数据还未写完,输出流就被close
Reader
  • 以字符为基本单位的输入流。
  • 基本方法与InputStream差不多,把byte[] buffer替换为char[] cbuf
Write
  • 以字符为基本单位的输出流。
  • 基本方法与OutputStream差不多,但是有多两个
    • void write(String string);
    • void write(String string, int offset, int length)//将字符串写入输出流
    • void flush()
节点流和处理流
  • 节点流可以从一个特定的数据源(节点)读写数据。如:文件,内存。
  • 处理流连接在已存在的流(节点流、处理流)之上,能够进行数据的处理为程序提供更为强大的读写功能。
  • 使用方法如下
BufferedWriter bw = new BufferedWriter(Writer w);
//将一个Writer类型的对象作为参数传入
复制代码
转换流
  • InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换
  • InputStreamReader需要和InputStream“套接”,OutputStreamWriter同理
数据流
  • 数据流属于处理流,需要套接在InputStream或OutputStream类型的节点流上,其提供了可以存取**(以字节的方式)**基本类型数据(如int、double等)的方法。即以字节的形式读进去,这样效率高且节约空间。
  • 其构造方法为DataInputStream(InputStream in)
  • ByteArrayInputStream和ByteArrayOutputStream
示范代码
public static void main(String[] args) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(baos);
		
		try {
			dos.writeDouble(Math.random());
			dos.writeBoolean(true);
			
			ByteArrayInputStream bais =
					new ByteArrayInputStream(baos.toByteArray());
			DataInputStream dis = new DataInputStream(bais);
			
			System.out.println(dis.readDouble());
			System.out.println(dis.readBoolean());
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
复制代码
PrintStream和PrintWriter
  • PrintStream属于输出流,可以将键盘的输入,输出到指定位置,比如:
PrintStream ps = new PrintStream(new FileOutputStream("c:/..."));
System.setOut(ps);
//从键盘输入的流会通过ps输出到指定文件中
复制代码

Object流

  • 用于直接将object写入或读出
  • 如果先要将某个类直接写入或读出,则需实现接口Serializable,将其序列化为字节流
  • 需要“套接”在OutputStream类对象上
transient关键字
  • 被transient关键字修饰的成员变量,在被写入硬盘的时候默认是0或null、false。

GUI Graphics User Interface

Frame类

  • 如果要创建窗口,最好自己定义一个窗口类,继承自Frame

Panel类

布局管理器接口LayoutManager

  • 实现布局管理器接口的类有:FLowLayout,BorderLayout,GridLayout,CardLayout,GridBagLayout
FlowLayout
new FlowLayout(FLowLayout.RIGHT, 20, 40);
//右对齐,水平间距20像素,行间距40像素
new FlowLayout(FlowLayout.LEFT);
//左对齐,水平间距和行间距默认为5
new FlowLayout();
//居中对齐
复制代码
BorderLayout
  • BorderLayout是Frame的默认布局管理器,它将整个容器划分成EAST,WEST,SOUTH,NORTH,CENTER五个区域,component只能被添加到这五个区域(默认添加到CENTER)
  • 一个区域只能添加一个component,如果加入多个,原先的会被覆盖
  • NORTH,SOUTH这两个区域只能在水平方向上缩放,WEST,EAST只能在垂直方向上缩放,CENTER可以在两个方向上缩放
GridLayout
f.setLayout(new GrideLayout(3,4));
//把f划分为3行4列,共12个一样大的区域
复制代码
注意
  • Frame的缺省布局管理器的BorderLayout,Panel的是FlowLayout
  • 当把Panel作为一个component添加到某个容器后,Panel仍然可以拥有自己的布局管理器

事件监听

  • 事件源对象:发生某些事件的component
  • 事件监听器:事件监听器是指实现了某种监听器接口的对象。当事件源对象发生某些事件的时候,会将*事件对象发送给监听器。
  • 注册:使某个监听器对象能够监听某个事件源对象,这个行为叫做注册。
  • 在事件监听器对象中,想要访问到事件源对象里面的属性,可以使用getSource方法。
TextField文本输入框
//加法运算器
import java.awt.*;
import java.awt.event.*;
public class Test {
	public static void main(String[] args) {
		new TFFrame().lanuchFrame();
	}
}

class TFFrame extends Frame {
	TextField num1, num2, num3;
	
	public void lanuchFrame() {
		num1 = new TextField(10);
		Label l = new Label("+");
		num2 = new TextField(10);
		Button b1 = new Button("=");
		b1.addActionListener(new MyMonitor(this));
		num3 = new TextField(11);
		
		setLayout(new FlowLayout());
		add(num1);
		add(l);
		add(num2);
		add(b1);
		add(num3);
		pack();
		setVisible(true);
		
	}
	
}

class MyMonitor implements ActionListener {
	TFFrame tf = null;
	
	public MyMonitor(TFFrame f) {
		this.tf = f;
	}
	
	public void actionPerformed(ActionEvent e) {
		int n1 = Integer.parseInt(tf.num1.getText());
		int n2 = Integer.parseInt(tf.num2.getText());
		
		tf.num3.setText("" + (n1 + n2));
	}
}
复制代码

鼠标适配器

内部类

以上代码可以利用内部类的原理简化,即将MyMonitor类直接在MyFrame类里面声明,这样MyMonitor的成员就可以直接访问MyFrame类的成员变量。

不希望让其他类访问某个类的时候,可以将其定义为内部类

Graphics类

  • 每个component都有一个paint(Graphics g)方法用以实现绘图目的,每次重画component的时候都重新调用paint方法

你可能感兴趣的:(JAVA学习笔记——基础语法)