Java郭克华笔记
class Pro1{
public static void main (String[] args) {
System.out.print("HelloWorld"); //不换行
System.out.println("HelloWorld"); //换行
}
}
变量和数据类型
数据类型:
整数
class Pro1{
public static void main (String[] args) {
//字节(1字节)、短整数(2字节)、整数(4字节)、长整数
byte b = 12;
short s = 45;
int i = 76445;
long l = 565455545345345L;//long定义要+L
b = (byte)s;//Java中,高精度不能赋值给低精度,除非强制转换
}
}
实数
class Pro1{
public static void main (String[] args) {
//float、double
float f = (float)3.14;//Java中,实数常量默认是double
double d = 3.1415926;
}
}
字符
class Pro1{
public static void main (String[] args) {
//char,和C相同,还有转义字符,和C基本相同
char c = '中';
int i = (int)c;
System.out.println(i); //打印 /^_^\
System.out.println("/^_^\\");
}
}
字符串
class Pro1{
public static void main (String[] args) {
//String 为字符串,比C简单
String s = "中南大学CSU";
System.out.println(s);
}
}
布尔
class Pro1{
public static void main (String[] args) {
//boolean true或者false
boolean b1 = true;
boolean b2 = false;
//Java中不能用数字表示真假
}
}
运算符
算术运算:+ - * / % 和C相同
关系运算:> < >= <= == != 和C相同
逻辑运算:&& || !和C相同
赋值运算:+= -= *= /= ++ --和C相同
程序流程
顺序 和C相同
选择 if-[else if]-else switch-case和C相同
循环 while do-while for 和C相同
控制 break continue 和C相同
4、数组 有较大不同
5、编译预处理 Java无
6、指针 Java无
7、结构体共同体 Java无
8、函数 和C基本相同,更简单
Java入门
Java语法基础
-变量和数据类型
-数据运算
-程序流程
数组
1、为什么需要数组?
C: int a[10];
a[0] a[1] … a[9]
int N = 10; int a[N]; 错误
一维数组
C: int a[10];
Java:
int[] a = new int[10];
int a[] = new int[10];
Java:
int[] a = new int[10]; //推荐
int a[] = new int[10];
额外知识:
1)、数组长度获取
数组名称.length;
class Pro1{
public static void main (String[] args) {
int[] a = new int[10];
int len = a.length();
System.out.println(len);
for(int i=0;i<len;i++){
System.out.println(a[i]);
}
}
}
2)、数组空间是动态分配的
定义步骤:
1、
class Pro1{
public static void main (String[] args) {
int[] a = new int[10];
int b[] = new int[10];
for(int i=0;i<10;i++){
a[i] = i+1;
}
for(int i=0;i<10;i++){
System.out.println(a[i]);
}
}
}
2、
class Pro1{
public static void main (String[] args) {
int N = 10;
int[] a = new int[N];
N = 100;
a = new int[N];
}
}
3、
class Pro1{
public static void main (String[] args) {
int[] a = new int[]{1,2,3};
int[] b = new int[]{4,5,6};
a = b;
a[0] = 1000;
System.out.println(b[0]);
}
}
遍历方法
class Pro1{
public static void main (String[] args) {
int[] a = new int[]{1,2,3,4,5};
for(int t : a){
System.out.println(t);
}
}
}
二维数组
C: int a[4] [5];
Java:
int[][] a = new int[4] [5];
int a[][] = new int[4] [5];
int []a[] = new int[4] [5];
1、
class Pro1{
public static void main (String[] args) {
int[][] a = new int[3][4];
int b[][] = new int[3][4];
int []c[] = new int[3][4];
}
}
2、
class Pro1{
public static void main (String[] args) {
int[][] a = new int[3][];
a[0] = new int[]{1,2,3};
a[1] = new int[]{1,2,3,4,5};
a[2] = new int[]{1,2,3,4,5,6,7,8};
int count = 0;
for(int i=0;i<a.length;i++){
count+=a[i].length;
}
System.out.println(count);
}
}
额外知识:
(1)二维数组实际上是一维数组的集合
int[][] a = new int[4][5];
实际上定义了4个一维数组,a[0]\a[1]…a[3]
每个一维数组,都有5个元素
如a[0]包含a[0][1]…a[0][4]
编写程序,打印一个二维数组中元素的个数
问题:Java数组能否扩充?不能
C数组能否扩充?不能
C: int a[10]; int* p = a;
int[] a = new int[N];
习题:
1、对数组进行冒泡排序(降序)
class Pro1{
public static void main (String[] args) {
int[] a = new int[]{34, 6, 3, 24, 78, 90, 25, 79, 76};
for(int j=0;j<a.length-1;j++){
for(int i=0;i<a.length-1-j;i++){
if(a[i]<a[i+1]) {
int t; t=a[i]; a[i]=a[i+1]; a[i+1]=t;
}
}
}
for(int t : a){
System.out.println(t);
}
}
}
2、计算根号2
class Pro1{
public static void main (String[] args) {
double d = 2;
double low = 0, high = d;
double mid=0;
for(int i=1;i<=1000;i++){
mid = (low+high)/2;
if(mid*mid>d) high=mid;
else low =mid;
}
System.out.println(mid);
}
}
3、随机数:Math.random()能够生成一个
大于等于0,小于1的double随机数
-将1-100整数字乱序放在数组a[0…99]中
class Pro1{
public static void main (String[] args) {
int[] a = new int[100];
for(int i=0;i<a.length;i++) a[i]=i+1;
for(int i=1;i<=1000;i++){
int L1 = (int)(100*Math.random());
int L2 = (int)(100*Math.random());
int t; t=a[L1]; a[L1]=a[L2]; a[L2]=t;
}
for(int t : a){
System.out.print(t + " ");
}
}
}
4、即使是公平的赌博游戏,久赌必输
class Pro1{
public static void main (String[] args) {
int mon = 100;
for(int i=1;i<=1000;i++){
double d = Math.random();
if(d<0.5) mon+=20;
else mon-=20;
if(mon==0) { System.out.print("输光 "); break;}
}
System.out.print("还剩:"+mon);
}
}
类
面向对象编程 Object Oriented Programming
C:面向过程编程 Procedure Oriented Programming
对象:功能的集合体
过程:函数,指代“功能”
这两种编程实现,来源于我们从什么角度看待软件
软件是功能的集合体 --面向过程
软件是对象的集合体,对象中包含功能–面向对象
例子:银行系统里面,用户的账号,密码,姓名,余额是基本信息,如果有很多顾客需要存储这些信息,如何定义变量呢?
-将账号,密码,姓名,余额打包定义为一个“顾客”类型,编程时,定义“顾客”,以后使用“顾客”类型
顾客就是一个个对象;打包定义实际上是定义“顾客”这个类型
编程角度,面向对象的两个基本概念:
类(class):定义了对象的共同特征
对象(Object):通过类,生成一个个对象
例子:将账号,密码,姓名,余额打包定义为一个“顾客”类(class),编程时,通过“顾客”类,生成一个个对象(Object)
类的定义:
class 类名{
相关变量或者函数
}
2、类生成对象
int a;
类名 对象名=new 类名();
3、通过对象访问对象中的变量
对象名.变量名
概念:
(1)类和对象的关系:抽象和具体
(2)类生成对象:又叫做:实例化对象;对象也被称为类的实例(instance)
(3)类里面的变量,又叫做成员变量,保存的是该类所有对象的基本信息(也叫做属性,或者叫做“域(Field)”)
(4)类中除了有属性以外,还可以定义功能,功能用函数表示;函数叫做成员函数,又叫做:方法(Method)
总结:类包含成员变量和成员函数,两者统称“成员”(Member)
class Customer{
String account;
String password;
String cname;
double balance;
public static void main (String[] args) {
Customer zs = new Customer();
Customer ls;
ls = new Customer();
zs.account = "zhangsan"; zs.balance = 1000;
ls.cname = "李四"; ls.balance = 5897;
System.out.println(zs.balance);
System.out.println(ls.balance);
}
}
2、
class Customer{
String account;
String password;
String cname;
double balance = 0;
void cunKuan(double money){
balance += money;
System.out.println("存款成功,余额为:" + balance);
}
public static void main (String[] args) {
Customer zs = new Customer();
zs.cunKuan(200);
zs.cunKuan(5000);
System.out.println(zs.balance);
}
}
对象的引用性质
Customer zs = new Customer();
zs的性质类似于C语言里面的指针,Java中叫做对象的引用名称,又叫做引用(reference)
zs.account
class Customer{
String account;
double balance;
public static void main (String[] args) {
Customer zs = new Customer();
Customer ls = new Customer();
zs.balance = 1000; ls.balance = 2000;
zs = ls;
zs.balance = 10000;
System.out.println(ls.balance);
}
}
扩充内容:对象数组,一次性定义很多对象,以数组形式保存
定义100个Customer对象, 每个对象初始值1000元。
int[] a = new int[100];
Customer[] a = new Customer[100];
通过循环,给每个元素逐个分配对象内存
class Customer{
String account;
int balance;
public static void main (String[] args) {
Customer[] customers = new Customer[100];
for(Customer cus : customers){
cus = new Customer();
cus.balance = 1000;
}
}
}
类和对象
成员变量和成员函数
对象的引用性质
对象数组
回顾:
面向对象基本概念
类(class)
对象(Object)
成员变量
成员函数
对象的引用性质
成员函数
1、为什么需要成员函数
实现功能的复用
2、Java中函数的类型
(1)无参数无返回类型的函数
void 函数名称(){
//函数体
}
1)void不能省略
2)可以通过return;语句跳出函数
(2)有参数无返回类型的函数
void 函数名称(参数定义列表,用逗号隔开){
//函数体
}
1)参数不能给默认值
2)函数中定义的参数叫形参;实际调用时传入的参数叫实参
(3)有参数有返回类型的函数
1)原则上,定义的返回类型和实际返回值类型一致
函数的参数传递
1、值传递:简单数据类型
2、引用传递:数组、对象
重载
问题:Java中能否定义多个同名的函数?
答案:可以
但是要满足以下条件之一:
1、参数个数不同
2、参数个数相同,类型不同
3、参数个数类型相同,出现顺序不同
注意:以下两种不能成为函数同名的条件
1、返回类型不同
2、参数名称不同
以上功能叫做:重载(overload)
重载:定义多个形参不同的函数,函数名相同;根据实参类型,自动匹配相应的函数,进行调用
重载:一个函数名称,在不同实参情况下,完成不同的功能
构造函数的作用:
对对象进行初始化
如何定义?
1)构造函数名称和类名相同
2)构造函数没有返回类型
3)可以定义多个构造函数(重载)
4)构造函数在实例化对象时传入参数
构造函数的性质?
1)构造函数在实例化对象时,自动调用1次
2)构造函数在对象生命周期中,只会自动调用1次,不可手动调用
3)如果类没有定义构造函数,系统自动给其一个空的不带参数的构造函数,如果定义了构造函数,该默认构造函数失效
思考:构造函数在对象生命周期中,只会自动调用1次,不可手动调用;如果对象在生命周期中要再次做初始化呢?
方法:将初始化工作写在初始化函数;构造函数调用初始化函数
this.变量名/函数名 特别标记该变量或函数为类中的成员
对象何时消亡?
对象成为内存垃圾之后(无任何引用指向该对象),垃圾搜集机制会根据系统情况,自动进行垃圾搜集,此时对象消亡
可否手动垃圾搜集?
System.gc(); 不建议经常手动垃圾搜集
finalize函数
对象消亡时,可以通过finalize函数完成一些工作,该函数由系统自动运行,格式如下:
protected void finalize(){ /函数体/ }
该函数根据情况编写。如果在对象消亡时,要执行一些除了内存释放之外的其他工作,可以编写该函数完成
1、
class Customer{
String account;
double balance;
void init(String a,double b){
account = a;
balance = b;
}
public static void main (String[] args) {
Customer zs = new Customer();
zs.init("zhangsan",1000);
System.out.println(zs.account);
}
}
2、
class Customer{
String account;
double balance;
Customer(String a,double b){
System.out.println("TEST");
account = a;
balance = b;
}
public static void main (String[] args) {
Customer zs = new Customer("zhangsan",1000);
System.out.println(zs.account);
}
}
3、
class Customer{
String account;
double balance;
Customer(String account,double balance){
this.account = account;
this.balance = balance;
}
protected void finalize(){
System.out.println("TEST");
}
public static void main (String[] args) {
Customer zs = new Customer("zhangsan",1000);
zs = new Customer("zs",2000);
//System.gc();
}
}
3、
class Customer{
double balance;
void test(Customer c){
c = new Customer();
c.balance = 5000;
}
public static void main (String[] args) {
Customer zs = new Customer();
zs.balance = 1000;
zs.test(zs);
System.out.println(zs.balance);
}
}
4、
class Calc{
int add(int a,int b){
return a+b;
}
int add(int a,int b,int c){
return a+b+c;
}
double add(double a,double b){
return a+b;
}
double add(double a,int b){
return 0;
}
public static void main (String[] args) {
Calc c = new Calc();
System.out.println(c.add(1.2,2));
}
}
0、复习
面向对象基本概念(类、对象、成员)
成员包括:成员变量、成员函数
函数重载、构造函数
static
静态变量
1)什么是静态变量
类中的成员变量,各个对象都各自拥有。
有无一种情况,某个成员变量,被类的各个对象共用?
静态变量支持此功能
2)如何定义?
在变量定义前,加static关键字
3)静态变量的性质
–被类的所有对象公用
–类不需要实例化,就可以直接使用静态变量(普通变量不行)
–可以用 类名.静态变量 来访问静态变量,并且建议这样做
–静态变量在类加载时就分配空间,普通变量在new(实例化)时才分配空间
普通成员变量 静态成员变量
类名. 不可以 可以
对象名. 可以 可以(不太推荐)
class Customer{
String account;
double balance;
static String bankName;
public static void main (String[] args) {
Customer zs = new Customer();
zs.bankName = "中国银行";
Customer ls = new Customer();
System.out.println(ls.bankName);
}
}
2、
class Customer{
String account;
double balance;
static String bankName;
public static void main (String[] args) {
Customer cus = null;
//cus.bankName = "中国银行";
Customer.bankName = "中国银行";
System.out.println(Customer.bankName);
}
}
3、
class Customer{
String account;
double balance;
static String bankName;
static void fun(){
System.out.println("这是一个静态函数");
}
void print(){
System.out.println(account);
}
public static void main (String[] args) {
Customer cus = new Customer();
cus.fun();
Customer.fun();//建议使用
}
}
静态函数
1)静态函数如何定义?
在函数名前面增加static关键字
2)静态函数的性质
–类不需要实例化,就可以直接使用静态函数(普通函数不行)
–可以用 类名.静态函数 来访问静态函数,并且建议这样做
–静态函数只能访问类中的静态成员,不能访问普通成员
普通成员变量 静态成员变量
静态函数 不可以 可以
普通函数 可以 可以(不推荐)
1、
class Customer{
String account;
double balance;
static String bankName;
static void fun(){
System.out.println("这是一个静态函数");
}
void print(){
System.out.println(account);
}
public static void main (String[] args) {
Customer.fun();
Customer zs = null; zs.print();
}
}
2、
class Customer{
String account;
double balance;
static String bankName;
static void fun(){
//balance = 1000;
bankName = "中国银行";
System.out.println("这是一个静态函数");
}
void print(){}
public static void main (String[] args) {
}
}
总结:
类 对象 成员
构造函数 函数重载 静态变量 静态函数
习题:
1、Customer类可以实例化多个对象,请为每个对象赋一个编号,编号从1开始,按照实例化顺序递增
class Customer{
String account;
static int count = 0;
int id;
Customer(){
count++;
id = count;
}
public static void main (String[] args) {
Customer cus1 = new Customer();
Customer cus2 = new Customer();
Customer cus3 = new Customer();
Customer cus4 = new Customer();
Customer cus5 = new Customer();
System.out.println(cus4.id);
}
}
2、探险游戏,五人一组,有的成员会牺牲。要求每个成员都可以知道当前组内还有多少人存活。
class Person{
static int count = 0;
Person(){
count++;
}
void die(){
count--;
if(count==3){ System.out.println("只剩下三人了!");}
}
void check(){
System.out.println("当前还剩下" + count + "人");
}
public static void main (String[] args) {
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
Person p4 = new Person();
Person p5 = new Person();
p3.die();
p5.check();
p4.die();
p1.check();
}
}
3、QQ登录界面,输入账号密码,密码正确则登录成功,到达聊天界面。请将账号传至聊天界面。
class Conf{
static String account;
}
class Login{
String password;
void login(){
Conf.account = "12345";
//以成功为例
Chat c = new Chat();
}
}
class Chat{
void send(){ //聊天
//Conf.account
}
}
class Test{
public static void main (String[] args) {
}
}
4、编写一个复数类,实现两个复数的加法
a + b i
class ComplexNumber{
int a, b;
ComplexNumber(int a,int b){ this.a=a; this.b=b;}
void display(){
System.out.println(a+"+"+b+"i");
}
static ComplexNumber add(ComplexNumber c1,ComplexNumber c2){
return new ComplexNumber(c1.a+c2.a, c1.b+c2.b);
}
public static void main (String[] args) {
ComplexNumber c1 = new ComplexNumber(1,5);
ComplexNumber c2 = new ComplexNumber(8,7);
ComplexNumber c = ComplexNumber.add(c1,c2); c.display();
}
}
2、
class ComplexNumber{
int a, b;
ComplexNumber(int a,int b){ this.a=a; this.b=b;}
void display(){
System.out.println(a+"+"+b+"i");
}
ComplexNumber add(ComplexNumber c){
this.a += c.a; this.b += c.b;
return this;
}
public static void main (String[] args) {
ComplexNumber c1 = new ComplexNumber(1,5);
ComplexNumber c2 = new ComplexNumber(8,7);
ComplexNumber c3 = new ComplexNumber(9,5);
ComplexNumber c = c1.add(c2).add(c3); c.display();
}
}
0、复习
面向对象基本概念
类、对象、成员变量、成员函数
函数重载、构造函数、静态变量、静态函数
面向对象的基本特征
1、封装(Encapsulation)
将用户需要的内容暴露,隐藏细节;将内容分门别类进行管理
1)包级封装
- 如何将类放在某个包中(以文件夹进行管理)
在类的定义上,标明: package 包名;
要点:
-编程规范:包的名字首字母一般小写
-可以定义包中的子包,定义时用 . 隔开
-用.定义的子包,和上层的包,并无隶属关系,只是各自的包名定义 bank bank.person 不是包含关系,这两个包是不同的包
-如何使用某个包中的类
-同一个包中的类,可以直接使用
-不在同一个包中的类,需要用
import 类路径 来导入。(前提:被导入的类是public类)
import 包名.*; 导入包中的所有类
2)类级封装
-主要特指:前面所述的 public类
public类在定义时,增加public关键字 public class XX{}
-规定:public类类名必须和类所在文件名相同
-性质:只有public类才能被包外的类导入并访问,普通类只能在同一个包中被访问
3)成员级封装
权限有4种:
–private:私有 只在类中能被访问
–无修饰:默认 能在类中访问;也可被同一包中其他类访问
–protected:保护 默认权限+可被包外子类访问
–public:公开 可被包内包外所有类访问
要点:
–建议:成员变量定义成私有;成员函数定义成公有
–通过成员函数来访问成员变量,确保访问安全
习题:
单例模式
编写代码,实现单例模式(某个对象在系统使用的过程中,永远保持不多于1个),以Windows的任务管理器为例
class TaskManager{
private static TaskManager tm = null;
private TaskManager(){
System.out.println("任务管理器初始化");
}
public static TaskManager getInstance(){
if(tm==null) { tm = new TaskManager();}
return tm;
}
public void display() { System.out.println("任务管理器显示");}
}
class Desktop{
public void click(){
TaskManager.getInstance().display();
}
public static void main (String[] args) {
Desktop d = new Desktop();
d.click(); d.click(); d.click();
}
}
2、继承
1、为什么需要继承
降低代码量,提高系统可维护性
2、如何实现继承?
-将共同的代码编写一个类
-将个体代码分别编写类
-个体代码继承共同代码类
如何继承?关键字:extends
要点:
-(1)FontDialog继承Dialog,FontDialog叫做子类,派生类或者扩展类;Dialog又叫做父类,基类或者超类
- (2)子类继承父类之后,父类中的成员可以像子类自己的成员一样被子类对象使用(私有的父类成员除外)
- (3)如果父类成员被子类使用,一般将父类成员定义为protected
- (4)Java不支持多重继承(同时继承多个父类)
3、子类中可否定义和父类格式相同的成员?
- 可以;此时子类对象调用时子类中的成员
- 该内容称为“覆盖”(override),或者“重写”
要点: - 覆盖时,不允许使得子类成员的访问权限更加严格
4、覆盖有何作用?
- 可以通过覆盖,实现子类对象某些属性或功能的个性化定制
5、如何在子类中调用父类成员?
用super来指代父类对象,调用相应成员
super和this是对应的
1、
class Dialog{
int w;
int h;
}
class FontDialog extends Dialog{
String fontName;
}
class ParaDialog extends Dialog{
int lineWidth;
}
class Test{
public static void main (String[] args) {
FontDialog fd = new FontDialog();
fd.w = 100;
}
}
2·
class Dialog{
int w;
int h;
public void show(){
System.out.println("Dialog显示");
}
}
class FontDialog extends Dialog{
String fontName;
public void show(){
super.show();
System.out.println("FontDialog显示");
}
}
class Test{
public static void main (String[] args) {
FontDialog fd = new FontDialog();
fd.show();
}
}
3、多态性
- 多态性:一个事物,在不同情况下呈现出不同形态
- 重载: 一个函数名,在不同参数传入下,实现不同功能
重载属于“静态多态性”;静态体现在:必须为多个函数功能编写相应函数
2、动态多态性
-
基本规则:父类引用指向子类对象
-
性质:父类引用调用被覆盖的成员时,调用的是子类对象中的成员
-
两种使用情况
–(1)形参定义父类类型,实参可以传入子类对象
FontDialog是Dialog的子类
void fun(Dialog d){ /**/ } 函数定义
fun(new FontDialog); 函数调用
案例:有FontDialog和ParaDialog两个类,在主界面类中,定义一个函数,可以将对话框在界面中居中。 -
多态性:一个事物,在不同情况下呈现出不同形态
-
重载: 一个函数名,在不同参数传入下,实现不同功能
-
动态多态性:一个函数,在不同子类对象参数传入情况下,实现不同功能
–(2)函数返回父类类型,实际返回子类对象
FontDialog 是Dialog的子类
Dialog fun(){ 函数定义
return new FontDialog();
}
Dialog d = fun();
d.show(); 函数调用
fun(new FontDialog); 函数调用
class Dialog{
public void show(){ System.out.println("Dialog.show"); }
}
class FontDialog extends Dialog{
public void show(){ System.out.println("FontDialog.show"); }
}
class Test{
public static void main (String[] args) {
Dialog d = new FontDialog();
d.show();
}
}
2
class Dialog{
public void show(){ System.out.println("Dialog.show"); }
}
class FontDialog extends Dialog{
public void show(){ System.out.println("FontDialog.show"); }
}
class ParaDialog extends Dialog{
public void show(){ System.out.println("ParaDialog.show"); }
}
class MainFrame{
public void toCenter(Dialog d){
/*计算界面坐标*/
d.show();
}
public static void main (String[] args) {
MainFrame mf = new MainFrame();
ParaDialog pd = new ParaDialog();
mf.toCenter(pd);
}
}
3
class Dialog{
public void show(){ System.out.println("Dialog.show"); }
}
class FontDialog extends Dialog{
public void show(){ System.out.println("FontDialog.show"); }
}
class ParaDialog extends Dialog{
public void show(){ System.out.println("ParaDialog.show"); }
}
class MainFrame{
public void toCenter(Dialog d){
/*计算界面坐标*/
d.show();
}
public static void main (String[] args) {
MainFrame mf = new MainFrame();
MyNewDialog mnd = new MyNewDialog();
mf.toCenter(mnd);
}
}
class MyNewDialog extends Dialog{
public void show(){
}
}
0、回顾
面向对象基本概念
- 类、对象
- 成员变量、成员函数
- 构造函数、函数重载、静态变量、静态函数
面向对象基本特征 - 封装
- 继承
- 多态性
7.1.3 继承的底层本质 自学抽象类和接口
抽象函数
就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类
-
含有抽象函数的类叫抽象类,用abstract修饰
-
抽象函数在函数定义时,用abstract修饰
-
性质
- 抽象函数必须被子类覆盖,除非子类也是抽象类
- 抽象类中也可以含有普通函数
- 抽象类不可以被实例化,只能被继承
-
要点
- 抽象类中如定义普通函数,有何作用?
接口
- 抽象类中除了可以含有抽象函数,还可以含有普通函数,还可以含有成员变量(为了子类使用)
- Java中定义了一种比抽象类更加“抽象”的“类”,叫做接口(Interface)
- 接口中只允许有抽象函数;抽象函数的abstract可以省略
- 接口中定义的变量,只能是public static的常量,定义时,public static可以省略
- 接口用interface来定义,用implements来“继承”,一般叫做“实现一个接口”
- 一个类可以同时实现多个接口,用 , 隔开
总结:抽象类和接口
- 作用:为了实现多态性编程时的标准化
abstract class Dialog{
public abstract void show();
}
class FontDialog extends Dialog{
public void show(){ System.out.println("FontDialog.show"); }
}
class Test{
public static void main (String[] args) {
Dialog d = new FontDialog();
d.show();
}
}
2
interface Dialog{
int N = 5;
void show();
}
class FontDialog implements Dialog{
public void show(){ System.out.println("FontDialog.show"); }
}
class Test{
public static void main (String[] args) {
Dialog d = new FontDialog();
d.show();
}
}
3
interface I1{
int N = 5;
void show();
}
interface I2{
int N = 6;
void show();
}
class FontDialog implements I1, I2{
public void show(){}
}
class Test{
public static void main (String[] args) {
System.out.println(FontDialog.N);
}
}
4
interface I1{
int show();
}
interface I2{
void show();
}
class FontDialog implements I1, I2{
public int show(){} //避免这种情况
public void show(){}
}
class Test{
public static void main (String[] args) {
}
}
其他内容: final关键字
- final类:该类不允许被继承
final class XXX{} - final函数:final函数不允许被子类覆盖
class XX{
final void fun(){}
} - final变量:必须定义时赋值,赋值后不允许再赋值,相当于常量
class XX{
final int i = 5;
}
————————————————————
练习
1、对软件功能进行扩充 - 自行编写一个软件,能够显示一幅图片
- 希望在显示图片前,对图片去噪声,该模块从网上下载
- 将以上两个模块拼接
class ImageShower{
public void show(){
System.out.println("显示图片");
}
}
//..........
class NoiseOpe{
public void clearNoise(){
System.out.println("去掉噪声");
}
}
//..........
interface INO{
void clearNoise();
}
class MyNoiseOpe extends NoiseOpe implements INO{}
class MyImageShower extends ImageShower{
INO no = null;
MyImageShower(INO no) { this.no = no; }
public void show(){
no.clearNoise();
super.show();
}
}
class Test{
public static void main (String[] args) {
INO no = new MyNoiseOpe();
ImageShower is = new MyImageShower(no);
is.show();
}
}
2、编写一个界面类,一个按钮类,界面上放一个按钮,点击按钮,界面变红
class Button{
I i = null;
Button(I i) { this.i = i; }
void click() { i.perform(); }
}
interface I{
void perform();
}
class MainFrame implements I{
Button b = new Button(this);
public void perform(){ turnRed(); }
void turnRed() { System.out.println("界面变红"); }
}
class Test{
public static void main (String[] args) {
MainFrame mf = new MainFrame();
mf.b.click();
}
}
2
class Button{
I i = null;
Button(I i) { this.i = i; }
void click() { i.perform(this); }
}
interface I{
void perform(Button b);
}
class MainFrame implements I{
Button b1 = new Button(this);
Button b2 = new Button(this);
public void perform(Button b){
if(b==b1) turnRed();
else if(b==b2) turnGreen();
}
void turnRed() { System.out.println("界面变红"); }
void turnGreen() { System.out.println("界面变绿"); }
}
class Test{
public static void main (String[] args) {
MainFrame mf = new MainFrame();
mf.b1.click();
}
}
0、回顾
面向对象基本概念
-
类、对象
-
成员变量、成员函数
-
构造函数、函数重载、静态变量、静态函数
面向对象基本特征 -
封装
-
继承
-
多态性
Java语言的基本功能
异常处理
什么是异常处理
- 异常(Exception),或者“例外”
- 软件出问题三个层次:(1)编译无法通过;(2)运行时异常;(3)逻辑错误
- 案例:输入一个数字,计算该数字平方并显示
异常的危害
- 向客户反馈不友好的信息
- 程序发生异常,自动在异常处终止
如何解决
?异常处理三个关键字
- try:将有可能出现异常的代码放在try中
- catch:将异常处理代码放在catch中
- 原理:try中代码,如果不出现异常,则正常执行完毕,不执行catch内代码;如果出现异常,掠过剩余部分,直接执行catch内代码。
- 要点:
- try后面可以接多个catch,分别处理不同种类的异常
- Java中常见的有哪些异常呢?
-NumberFormatException:数值格式异常
-NullPointerException:空引用异常
- finally:如果一段代码,不管是否有异常都必须运行,那就放在finally中! finally能够确保try中不管出现什么情况,都会执行1次!
- try(1)+catch(1+)+finally(0,1)
- 异常处理有时候可以简化程序控制
- 案例:输入一个数字,计算该数字平方并显示,如果用户输入格式有误,输入框不断重复显示,直到输入正确为止
异常自定义:
两个关键词
-
throws :定义该函数可能会抛出异常对象
-
throw : 在程序中抛出一个异常对象
-
案例:编写一个函数,setAge,输入一个年龄,如果年龄在0-100之间,返回年龄;否则返回“年龄错误”。
-
throws和throw支持异常自定义并且在函数中链式传递
-支持异常的就地捕获和异常的再次抛出例题:自定义非法年龄类IllegalAgeException,定义一个Person类,包含年龄,姓名,性别等属性,编写属性设置和读取函数,在设置年龄函数中,判断参数是否符合要求(1~150),如果不符合则抛出异常,编写main函数进行测试。
package one; import java.util.*; class IllealException extends Exception { String msg=new String(); IllealException(String msg) { this.msg=msg; } public String getMessage() { return msg; } } public class Person { private String name; private String sex; private int age; Person()throws Exception { Scanner scanner=new Scanner(System.in); System.out.print("请输入姓名:"); String name=scanner.next(); System.out.print("请输入性别:"); String sex=scanner.next(); System.out.print("请输入年龄:"); int age=scanner.nextInt(); setName(name); setSex(sex); setAge(age); } void setName(String name) { this.name=name; } void setSex(String sex) { this.sex=sex; } String getName() { return name; } String getSex() { return sex; } void setAge(int age)throws IllealException { if(age>150||age<1) { throw new IllealException("年龄错误!"); } this.age=age; } int getAge() { return age; } public static void main(String[]a)throws Exception { new Person(); } }
class Test{
public static void main (String[] args) {
String str = javax.swing.JOptionPane.showInputDialog("请输入");
double d = Double.parseDouble(str);
System.out.println("AAAAAAAAAAAAAAAA");
double result = d * d;
System.out.println("平方是:" + result);
}
}
2\
class Test{
public static void main (String[] args) {
try{
String str = javax.swing.JOptionPane.showInputDialog("请输入");
double d = Double.parseDouble(str);
double result = d * d;
System.out.println("平方是:" + result);
}catch(Exception e){
System.out.println("数值计算异常!");
}
System.out.println("AAAAAAAAAAAA");
}
}
3
class Test{
public static void main (String[] args) {
try{
String str = javax.swing.JOptionPane.showInputDialog("请输入");
double d = Double.parseDouble(str);
double result = d * d;
System.out.println("平方是:" + result);
}catch(NumberFormatException e){
System.out.println("数值格式异常!");
}catch(NullPointerException e){
System.out.println("错误点击撤销按钮");
}catch(Exception e){
System.out.println("程序出现异常");
}
}
}
4
class Test{
public static void main (String[] args) {
try{
String str = javax.swing.JOptionPane.showInputDialog("请输入");
double d = Double.parseDouble(str);
double result = d * d;
System.out.println("平方是:" + result);
return;
}catch(Exception e){
System.out.println("数值计算异常!");
}
finally{ System.out.println("AAAAAAAAAAAA"); }
}
}
5
class Test{
public static void main (String[] args) {
while(true){
try{
String str = javax.swing.JOptionPane.showInputDialog("请输入");
double d = Double.parseDouble(str);
double result = d * d;
System.out.println("平方是:" + result);
break;
}catch(Exception e){
javax.swing.JOptionPane.showMessageDialog(null,"输入错误");
}
}
}
}
6
class AgeException extends Exception{
String msg;
AgeException(String msg){ this.msg = msg; }
public String getMessage(){ return msg; }
}
class Test{
int setAge(int age) throws AgeException{
if(age>100||age<0){
throw new AgeException("年龄错误:" + age);
}
return age;
}
public static void main (String[] args) {
Test t = new Test();
try{ //异常的就地捕获
int a = t.setAge(1000);
}catch(AgeException ae) { System.out.println(ae.getMessage()); }
}
}
7
class AgeException extends Exception{
String msg;
AgeException(String msg){ this.msg = msg; }
public String getMessage() { return msg; }
}
class Test{
int setAge(int age) throws AgeException{
if(age>100||age<0){
throw new AgeException("年龄错误:" + age);
}
return age;
}
public static void main (String[] args) throws AgeException{//再次抛出
Test t = new Test();
int a = t.setAge(1000);
}
}
8
class AgeException extends Exception{
String msg;
AgeException(String msg){ this.msg = msg; }
public String getMessage() { return msg; }
}
class Test{
int setAge(int age) throws AgeException{
if(age>100||age<0){
throw new AgeException("年龄错误:" + age);
}
return age;
}
void callSetAge() throws AgeException{
int a = setAge(1000);
}
public static void main (String[] args) {
Test t = new Test();
try{t.callSetAge();}
catch(AgeException ae){ System.out.println(ae.getMessage()); }
}
}
0、回顾
面向对象基本概念
- 类、对象
- 成员变量、成员函数
- 构造函数、函数重载、静态变量、静态函数
面向对象基本特征 - 封装
- 继承
- 多态性
Java语言的基本功能 - Java异常处理
- Java常用API
Java常用API
1、Java程序员必须学会看Java文档
java.lang包:
Java语言核心包,包含了Java编程中最核心的类或者接口,该包不需要被import,即可使用
-
数值运算:java.lang.Math
class Test{ public static void main (String[] args) { System.out.println(Math.PI); System.out.println(Math.cos(Math.PI/3)); System.out.println(Math.pow(2,0.5)); } }
-
字符串处理:
- (1)java.lang.String 不变字符串
注意:判断两个字符串是否相等,不要用==号,用equals函数 - (2)java.lang.StringBuffer 自变字符串(省内存)
class Test{ public static void main (String[] args) { String str = "Central South University,中南大学"; System.out.println(str.charAt(5)); System.out.println(str.contains("中")); } } 2 class Test{ public static void main (String[] args) { String str1 = "China"; String str2 = "China"; String str3 = new String("China"); System.out.println(str1==str2); System.out.println(str1==str3); System.out.println(str1.equals(str3)); //正确 } } 3 class Test{ public static void main (String[] args) { StringBuffer str1 = new StringBuffer("China"); str1.replace(3,4,"AA"); System.out.println(str1); } }
- (1)java.lang.String 不变字符串
-
10.4 基本数据类型的包装类
- 最常见的功能:将字符串转成相应的类型(如数值)
java.util包:
Java常见工具包
-
最重要的内容:Java集合(Java变长数组)
-
(1)一维变长数组
-
元素有顺序有位置的一维变长数组
- java.util.ArrayList: 底层用数组实现
- java.util.LinkedList:底层用链表实现
- java.util.Vector: 实现了线程安全
-
元素无顺序无位置的一维变长数组
-java.util.HashSetimport java.util.*; class Test{ public static void main (String[] args) { Vector<String> list = new Vector<String>(); list.add("北京"); list.add("纽约"); list.add("巴黎"); list.add(1,"东京"); list.remove(2); list.set(0,"Beijing"); for(int i=0;i<list.size();i++){ System.out.println(list.get(i)); } } } 2 import java.util.*; class Test{ public static void main (String[] args) { HashSet<String> set = new HashSet<String>(); set.add("北京"); set.add("纽约"); set.add("巴黎"); set.add("东京"); set.remove("巴黎"); for(String s : set){ System.out.println(s); } } }
-
-
(2)二维变长数组
-
java.util.HashMap: 11.3 Java中的二维集合
多线程
回顾
面向对象基本概念
- 类、对象、成员变量、成员函数
- 构造函数、函数重载、静态变量、静态函数
面向对象基本特征 - 封装、继承、 多态性
Java语言的基本功能 - Java异常处理
- Java常用API
- Java多线程开发
线程(Thread)
- 进程(Process):操作系统中,“同时”运行的多个程序
- 线程(Thread):一个应用程序中,“同时”运行的多个任务,例如:一边下载,一边播放;等等
如何实现多线程
案例:下载文件,播放文件,如果不用多线程,将会串行运行
实现多线程两种方法
1、让线程所在的类继承java.lang.Thread;将线程实现代码写在从Thread中重写的run函数中;使用线程类的start函数,启动线程,调用run
class Downloader extends Thread{//①
public void run(){ //②
for(int i=1;i<=10;i++){
try{ Thread.sleep(1000);} catch(Exception e){}
System.out.println("下载进度:" + i*10 + "%");
}
}
}
class Player extends Thread{
public void run(){
for(int i=1;i<=10;i++){
try{ Thread.sleep(1000);} catch(Exception e){}
System.out.println("播放进度:" + i*10 + "%");
}
}
}
class Test{
public static void main (String[] args) {
Downloader d = new Downloader();
Player p = new Player();
d.start(); //③
p.start();
}
}
2、让线程所在的类实现java.lang.Runnable接口; 将线程实现代码写在从Runnable中重写的run函数中; 实例化该类对象,将对象传入新的线程对象,使用其start函数,调用run
有何区别?如何选择?
方法1,让代码直接成为线程对象;方法2,让代码可以包装进线程对象;方法1相当于线程独立运行,方法2让代码依附线程运行;方法2可以让一段代码依附多个线程,实现“一段代码的多线程化”;实际上使用时,方法2因为是实现了Runnable接口,因此同时类还可以继承其他类;
class AAA extends XXX implements Runnable{}
class Downloader implements Runnable{//①
public void run(){ //②
for(int i=1;i<=10;i++){
try{ Thread.sleep(1000);} catch(Exception e){}
System.out.println("下载进度:" + i*10 + "%");
}
}
}
class Player implements Runnable{
public void run(){
for(int i=1;i<=10;i++){
try{ Thread.sleep(1000);} catch(Exception e){}
System.out.println("播放进度:" + i*10 + "%");
}
}
}
class Test{
public static void main (String[] args) {
Downloader d = new Downloader();
Player p = new Player();
Thread t1 = new Thread(d); //③
Thread t2 = new Thread(p);
t1.start();
t2.start();
}
}
线程的控制
-
包括线程开始、暂停、继续、终止
-
线程开始:start函数
-
线程暂停:suspend函数
-
线程继续:resume
-
终止: stop
class Downloader extends Thread{//① public void run(){ //② for(int i=1;i<=10;i++){ try{ Thread.sleep(1000);} catch(Exception e){} System.out.println("下载进度:" + i*10 + "%"); } } } class Test{ public static void main (String[] args) throws Exception{ Downloader d = new Downloader(); d.start(); Thread.sleep(3000); d.suspend(); Thread.sleep(4000); d.resume(); Thread.sleep(2000); d.stop(); } }
-
----以上方法是不安全的,要避免使用!因为以上方法有deadlock-prone(可能造成死锁)
-
suspend函数在线程暂停时,仍然持有线程占用的资源,其他线程不能访问该资源,只能等待resume之后运行完毕释放后才能访问。如果循环等待,则造成死锁
-
如何解决?不要使用上面几个函数
- 线程暂停,就是让线程结束;线程重新开始,就是新开启线程;线程结束的标志:run函数运行完毕
-注意保存线程暂停之后的运行状态(保存现场)
- 线程暂停,就是让线程结束;线程重新开始,就是新开启线程;线程结束的标志:run函数运行完毕
class Downloader extends Thread{//①
boolean RUN = true;
static int percent = 1;
public void run(){ //②
for(int i=percent;i<=10 && RUN;i++){
try{ Thread.sleep(1000);} catch(Exception e){}
System.out.println("下载进度:" + i*10 + "%");
percent = i+1;
}
}
}
class Test{
public static void main (String[] args) throws Exception{
Downloader d = new Downloader();
d.start();
Thread.sleep(3000);
d.RUN = false;
Thread.sleep(4000);
d = new Downloader();
d.start();
Thread.sleep(2000);
d.RUN = false;
}
}
0、回顾
面向对象基本概念
- 类、对象、成员变量、成员函数
- 构造函数、函数重载、静态变量、静态函数
面向对象基本特征 - 封装、继承、 多态性
Java语言的基本功能 - Java异常处理
- Java常用API
- Java多线程开发
- JavaIO操作
JavaIO操作
输出数位控制
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 第一种
DecimalFormat df = new DecimalFormat("#0.00");
float data;
data = sc.nextFloat();
System.out.println(df.format(data));
// 第二种,模仿c语言的输出方式
System.out.printf("%.2f\n", data);
// 第三种
System.out.println(String.format("%.2f", data));
}
}
1、IO:输入输出
- 输入设备:键盘、鼠标…
- 输出设备:显示器、打印机…
- 划分标准:站在内存角度
- 硬盘既是输入设备(可以从硬盘读取文件),又是输出设备(将内容保存到文件)
-最常见的输入输出是:文件输入输出 - 重点:文件输入(读文件)输出(写文件)
2、Java输入输出功能集中在java.io包
- 文件操作
- 文件读
- 文件写
3、文件操作:java.io.File类
- 查询文件、删除文件、重命名、创建文件夹
- 复制、移动文件等功能不涉及
文件删除
import java.io.*;
class Test{
public static void main (String[] args) {
File f = new File("d:/111");
f.delete();
}
}
查询文件
import java.io.*;
class Test{
public static void main (String[] args) {
File f = new File("d:/111");
f.delete();
}
}
文件读
案例:某文件中有一段字符串,请将其读入内存后显示
-
java.io.FileInputStream : 字节流,对中文乱码支持不好
import java.io.*; class Test{ public static void main (String[] args) throws Exception{ File f = new File("d:/test.txt"); FileInputStream fis = new FileInputStream(f); byte[] data = new byte[(int)f.length()]; fis.read(data); String str = new String(data); System.out.println(str); fis.close(); } }
import java.io.*; class Test{ public static void main (String[] args) throws Exception{ File f = new File("d:/test.txt"); FileInputStream fis = new FileInputStream(f); while(true){ int i = fis.read(); if(i==-1) break; System.out.print((char)i); } fis.close(); } }
-
java.io.FileReader:字符流,支持多字节字符
import java.io.*;
class Test{
public static void main (String[] args) throws Exception{
File f = new File("d:/test.txt");
FileReader fis = new FileReader(f);
while(true){
int i = fis.read();
if(i==-1) break;
System.out.print((char)i);
}
fis.close();
}
}
- java.io.BufferedReader:缓冲读,支持字符按行读
import java.io.*;
class Test{
public static void main (String[] args) throws Exception{
File f = new File("d:/test.txt");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
while(true){
String str = br.readLine();
if(str==null) break;
System.out.println(str);
}
fr.close();
}
}
文件写
案例:字符串“中南大学CSU”,请将其保存到文件
- java.io.FileOutputStream : 字节流,对中文乱码支持不好
import java.io.*;
class Test{
public static void main (String[] args) throws Exception{
File f = new File("d:/test.txt");
FileOutputStream fos = new FileOutputStream(f,true);
String str = "中南大学CSU";
byte[] data = str.getBytes();
fos.write(data);
fos.close();
}
}
-
java.io.FileWriter:字符流,支持多字节字符(使用少)
-
java.io.PrintStream:支持丰富的格式写
- 案例:将一个99乘法表存入文件test.txt
import java.io.*; class Test{ public static void main (String[] args) throws Exception{ File f = new File("d:/test.txt"); PrintStream ps = new PrintStream(f); for(int i=1;i<=9;i++){ for(int j=1;j<=i;j++){ ps.print(i + "*" + j + "=" + i*j + " "); } ps.println(); } ps.close(); } }
综合案例
1、将文件从一个地方拷贝到另一个地方
import java.io.*;
class Test{
public static void main (String[] args) throws Exception{
FileInputStream fis = new FileInputStream("板书.txt");
FileOutputStream fos = new FileOutputStream("板书2.txt");
while(true){
int i = fis.read();
if(i==-1) break;
fos.write(i);
}
fos.close();
fis.close();
}
}
2、将文件加密(每个字节数字+3)China->Fklqd
-加密算法 -密钥
import java.io.*;
class Test{
public static void main (String[] args) throws Exception{
FileInputStream fis = new FileInputStream("板书.txt");
FileOutputStream fos = new FileOutputStream("板书加密.txt");
while(true){
int i = fis.read();
if(i==-1) break;
fos.write(i+3);
}
fos.close();
fis.close();
}
}
import java.io.*;
class Test{
public static void main (String[] args) throws Exception{
FileInputStream fis = new FileInputStream("板书加密.txt");
FileOutputStream fos = new FileOutputStream("板书解密.txt");
while(true){
int i = fis.read();
if(i==-1) break;
fos.write(i-3);
}
fos.close();
fis.close();
}
}
5、照片加密
import java.io.*;
class Test{
public static void main (String[] args) throws Exception{
FileInputStream fis = new FileInputStream("img加密.jpg");
FileOutputStream fos = new FileOutputStream("img解密.jpg");
while(true){
int i = fis.read();
if(i==-1) break;
fos.write(i-3);
}
fos.close();
fis.close();
}
}
面向对象基本概念
- 类、对象、成员变量、成员函数
- 构造函数、函数重载、静态变量、静态函数
面向对象基本特征 - 封装、继承、 多态性
Java语言的基本功能 - Java异常处理、Java常用API、Java多线程开发、JavaIO操作
Java应用开发
用Swing开发GUI程序
- Swing:Java中支持GUI程序开发的包: javax.swing
- GUI:图形用户界面(视窗界面,代表:桌面应用程序)
- GUI三个层次:界面、控件、渲染
界面开发
-使用的类:javax.swing.JFrame、JWindow、JDialog
-
最常见的:JFrame
-
案例:在桌面显示一个JFrame
1、
import javax.swing.*;
class Test{
public static void main (String[] args) {
JFrame jfm = new JFrame("这是第一个界面");
jfm.setLocation(100,200);
jfm.setSize(300,300);
jfm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jfm.setVisible(true);
}
}
2、
import javax.swing.*;
class TestFrame extends JFrame{
public TestFrame(){
this.setTitle("这是第一个界面");
this.setLocation(100,200);
this.setSize(300,300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main (String[] args) {
TestFrame tf = new TestFrame();
}
}
控件
-
面板:javax.swing.JPanel 容纳控件,更好的布局
一般情况:界面上添加面板,面板上添加控件 -
按钮:javax.swing.JButton
-
文本框:javax.swing.JTextField
-
界面静态文本:javax.swing.JLabel
-
密码框: javax.swing.JPasswordField
-
下拉菜单:javax.swing.JComboBox
-
单选按钮:JRadioButton
-
复选框 :JCheckBox
-
多行文本框:JTextArea
-
菜单 :JMenuBar /JMenu /JMenuItem
-
…
-
看文档、看构造函数、面板上添加控件!
import javax.swing.*; class TestFrame extends JFrame{ private JPanel jpl = new JPanel(); private JButton jbt = new JButton("注册新用户"); private JLabel jlb = new JLabel("输入您的姓名"); private JTextField jtf = new JTextField(10); private JComboBox jcb = new JComboBox(); public TestFrame(){ this.add(jpl); jpl.add(jbt); jpl.add(jlb); jpl.add(jtf); jpl.add(jcb); jcb.addItem("男") ; jcb.addItem("女"); this.setSize(300,600); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } public static void main (String[] args) { TestFrame tf = new TestFrame(); } }
渲染
-
颜色
- 界面和控件都可以设置背景颜色和前景颜色
- 前景颜色主要是控件上文字的颜色
- setBackground设置背景颜色;setForeground设置前景颜色
- 案例:将按钮背景设置蓝色,前景设置黄色
-
字体
- 有文字的控件,都可以设置字体,用setFont函数
- 案例:将文本框文字设置大一些
-
图标
-
有些控件,如按钮,上面可以设置图标,setIcon函数
-
在按钮上设置一个图标
import javax.swing.*; import java.awt.*; class TestFrame extends JFrame{ private JPanel jpl = new JPanel(); private JButton jbt = new JButton("注册新用户"); public TestFrame(){ this.add(jpl); jpl.add(jbt); jpl.setBackground(new Color(200, 200, 200)); jbt.setBackground(Color.BLUE); jbt.setForeground(Color.YELLOW); this.setSize(300,600); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } public static void main (String[] args) { TestFrame tf = new TestFrame(); } } 2、 import javax.swing.*; import java.awt.*; class TestFrame extends JFrame{ private JPanel jpl = new JPanel(); private JButton jbt = new JButton("注册新用户"); public TestFrame(){ this.add(jpl); jpl.add(jbt); Icon icon = new ImageIcon("img.jpg"); jbt.setIcon(icon); this.setSize(300,600); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } public static void main (String[] args) { TestFrame tf = new TestFrame(); } }
-
案例:
-
界面上有一个面板,要求面板颜色从黑色渐渐变成白色
import javax.swing.*; import java.awt.*; class TestFrame extends JFrame implements Runnable{ private JPanel jpl = new JPanel(); public void run(){ for(int i=0;i<=255;i++){ Color c = new Color(i, i, i); jpl.setBackground(c); try{ Thread.sleep(10); } catch(Exception e){} } } public TestFrame(){ this.add(jpl); this.setSize(300,600); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); new Thread(this).start(); } public static void main (String[] args) { TestFrame tf = new TestFrame(); } }
-
界面从桌面顶端掉下来
import javax.swing.*; import java.awt.*; class TestFrame extends JFrame implements Runnable { int X = 0, Y = 0; public TestFrame(){ this.setSize(300,100); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); new Thread(this).start(); } public void run(){ while(true){ X++; Y=X*X; this.setLocation(X,Y/50); try{ Thread.sleep(100); }catch(Exception ex){} } } public static void main (String[] args) { TestFrame tf = new TestFrame(); } }
-
越掉越快;掉下来弹起来怎么做?围绕一个中心圆周运动怎么做?需要用到一点数学知识
Java事件处理
前提知识
- 事件:Event
- 什么是事件?程序对某种操作的响应
- 使用的包:java.awt.event包
如何处理事件?
- 界面上有一个按钮,点击,控制台打印“Hello”
- 事件响应对象必须能够监听到事件发出对象的命令
- 按钮点击命令,由ActionListener监听
- 事件响应对象必须能够响应事件
- 按钮点击事件,由actionPerformed函数处理
- 事件发出对象和事件响应对象绑定
- 调用按钮的绑定函数:addActionListener
总结:①实现监听接口;②编写处理函数;③绑定
- 调用按钮的绑定函数:addActionListener
-举一反三:为什么Java的事件处理机制如此设计?
- 案例:按钮点击,界面上打印“Hello”
需要注意的问题
- 按钮点击命令,由ActionListener监听,Java底层设定
- 各种事件,分别由什么Listener监听呢?后面一并总结
- actionPerformed(ActionEvent e)
- ActionEvent代表什么?封装了事件发出者的信息
- 例:界面上两个按钮,点击,分别让界面改变不同颜色
总结:①实现监听接口;②编写处理函数;③绑定
————以上叫做事件监听机制——————
Java事件由对应的Listener监听
- ***** ActionListener:按钮单击;文本框回车;菜单单击;其他拥有addActionListener函数的控件(见文档)
- *AdjustmentListener:主要用于类似滚动条等调整功能的控件
- *FocusListener:主要用于控件获得/失去焦点时响应事件
- ***ItemListener:用于选项有变化时响应事件(如下拉菜单等)
- 例:界面上一个下菜单,通过选择可以让界面变颜色
- ****MouseListener:监听鼠标事件(点击,进入/退出控件区域等)
- 鼠标进入界面,界面变颜色,退出,变为另一种颜色
- ****MouseMotionListener:监听鼠标事件(移动拖动)
- 鼠标在界面上移动,界面标题实时变为鼠标当前坐标值
- ****KeyListener:监听键盘事件
总结:
1、Java事件监听机制:三步骤
①实现监听接口;②编写处理函数;③绑定
2、事件监听机制原理
3、Java常见事件监听(举一反三)
import javax.swing.*;
import java.awt.event.*;
class Printer implements ActionListener{ //①实现监听接口
public void actionPerformed(ActionEvent e){ //②编写处理函数
System.out.println("Hello");
}
}
class EventTest1 extends JFrame{
private JButton jbt = new JButton("按钮");
private JPanel jpl = new JPanel();
public EventTest1(){
this.add(jpl);
jpl.add(jbt);
jbt.addActionListener(new Printer()); //③绑定
this.setSize(300,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main (String[] args) {
new EventTest1();
}
}
2、
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class EventTest2 extends JFrame implements ActionListener{//①实现监听接口
private JButton jbt = new JButton("按钮");
private JPanel jpl = new JPanel();
public EventTest2(){
this.add(jpl);
jpl.add(jbt);
jbt.addActionListener(this); //③绑定
this.setSize(300,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e){ //②编写处理函数
jpl.setBackground(Color.yellow);
}
public static void main (String[] args) {
new EventTest2();
}
}
3、
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class EventTest2 extends JFrame implements ActionListener{//①实现监听接口
private JButton jbt = new JButton("按钮");
private JPanel jpl = new JPanel();
public EventTest2(){
this.add(jpl);
jpl.add(jbt);
jbt.addActionListener(this); //③绑定
this.setSize(300,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e){ //②编写处理函数
jpl.setBackground(Color.yellow);
}
public static void main (String[] args) {
new EventTest2();
}
}
4、
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class EventTest2 extends JFrame implements ActionListener{//①实现监听接口
private JButton jbt1 = new JButton("按钮1");
private JButton jbt2 = new JButton("按钮2");
private JPanel jpl = new JPanel();
public EventTest2(){
this.add(jpl);
jpl.add(jbt1); jpl.add(jbt2);
jbt1.addActionListener(this); //③绑定
jbt2.addActionListener(this);
this.setSize(300,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e){ //②编写处理函数
if(e.getSource()==jbt1){
jpl.setBackground(Color.yellow);
}else{
jpl.setBackground(Color.blue);
}
}
public static void main (String[] args) {
new EventTest2();
}
}
5、
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class EventTest2 extends JFrame implements ItemListener{
private JComboBox jcb = new JComboBox();
private JPanel jpl = new JPanel();
public EventTest2(){
jcb.addItemListener(this);
this.add(jpl);
jpl.add(jcb);
jcb.addItem("红");
jcb.addItem("绿");
jcb.addItem("蓝");
this.setSize(300,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public void itemStateChanged(ItemEvent e){
String str = (String)jcb.getSelectedItem();
if(str.equals("红")){
jpl.setBackground(Color.red);
}else if(str.equals("绿")){
jpl.setBackground(Color.green);
}else{
jpl.setBackground(Color.blue);
}
}
public static void main (String[] args) {
new EventTest2();
}
}
6、
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class EventTest2 extends JFrame implements MouseListener {
private JPanel jpl = new JPanel();
public EventTest2(){
this.add(jpl);
this.addMouseListener(this);
this.setSize(300,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e) {
jpl.setBackground(Color.red);
}
public void mouseExited(MouseEvent e) {
jpl.setBackground(Color.blue);
}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public static void main (String[] args) {
new EventTest2();
}
}
7、
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class EventTest2 extends JFrame implements MouseMotionListener {
private JPanel jpl = new JPanel();
public EventTest2(){
this.add(jpl);
this.addMouseMotionListener(this);
this.setSize(300,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public void mouseDragged(MouseEvent e){
String s = e.getX() + "," +e.getY();
this.setTitle(s);
}
public void mouseMoved(MouseEvent e) {}
public static void main (String[] args) {
new EventTest2();
}
}
Layout
前提知识
- 布局:Layout
- 什么是布局?界面元素的排布和变化规律
- 案例:计算器
- 开发布局,用到Java中的哪个包?
- java.awt
- 文档浏览
2、案例引入:界面上放10个按钮
流式布局(FlowLayout)
-
从左到右,从上到下排布;JPanel默认是这种布局方式
-
该布局由java.awt.FlowLoyout管理;通过容器的setLayout函数可以设置
import javax.swing.*; import java.awt.*; class LayoutTest1 extends JFrame{ private JPanel jpl = new JPanel(); public LayoutTest1(){ FlowLayouut fl=new FlowLayout(); jpl.setLayout(fl); JButton[] bts = new JButton[10]; for(int i=0; i<10; i++){ bts[i] = new JButton("按钮"+i); jpl.add(bts[i]); } this.add(jpl); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setSize(800,600); this.setVisible(true); } public static void main (String[] args) { new LayoutTest1(); } }
网格布局(GridLayout)
-
将容器分为多行多列;例如计算器中的数字面板
-
案例:界面上放置24个按钮,6行,4列
import javax.swing.*; import java.awt.*; class LayoutTest1 extends JFrame{ private JPanel jpl = new JPanel(); public LayoutTest1(){ jpl.setLayout(new GridLayout(6,4,5,5)); JButton[] bts = new JButton[24]; for(int i=0; i<24; i++){ bts[i] = new JButton("按钮"+i); jpl.add(bts[i]); } this.add(jpl); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setSize(800,600); this.setVisible(true); } public static void main (String[] args) { new LayoutTest1(); } }
-
案例:界面上添加一个国际象棋棋盘,8*8,黑白交错
import javax.swing.*;
import java.awt.*;
class LayoutTest1 extends JFrame{
private JPanel jpl = new JPanel();
public LayoutTest1(){
jpl.setLayout(new GridLayout(8,8));
JPanel[][] pls = new JPanel[8][8];
for(int i=0; i<8; i++){
for(int j=0; j<8; j++){
pls[i][j] = new JPanel();
if((i+j)%2==0){
pls[i][j].setBackground(Color.white);
}else{
pls[i][j].setBackground(Color.black);
}
jpl.add(pls[i][j]);
}
}
this.add(jpl);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(800,600);
this.setVisible(true);
}
public static void main (String[] args) {
new LayoutTest1();
}
}
边界布局(BorderLayout)
- 将容器分为东西南北中五个位置;上北下南左西右东
import javax.swing.*;
import java.awt.*;
class LayoutTest1 extends JFrame{
private JPanel jpl = new JPanel();
public LayoutTest1(){
jpl.setLayout(new BorderLayout());
jpl.add(new JButton("按钮东"), BorderLayout.EAST);
jpl.add(new JButton("按钮西"), BorderLayout.WEST);
jpl.add(new JButton("按钮南"), BorderLayout.SOUTH);
jpl.add(new JButton("按钮北"), BorderLayout.NORTH);
jpl.add(new JButton("按钮中"), BorderLayout.CENTER);
this.add(jpl);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(800,600);
this.setVisible(true);
}
public static void main (String[] args) {
new LayoutTest1();
}
}
空布局(万能布局)
- 将容器的Layout设置为null,然后用坐标来确定容器中的元素位置
import javax.swing.*;
import java.awt.*;
class LayoutTest1 extends JFrame{
private JPanel jpl = new JPanel();
public LayoutTest1(){
jpl.setLayout(null);
JButton jbt = new JButton("按钮");
jbt.setLocation(300,200);
jbt.setSize(200,400);
jpl.add(jbt);
this.add(jpl);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(800,600);
this.setVisible(true);
}
public static void main (String[] args) {
new LayoutTest1();
}
}
习题
1、界面上一副图片,鼠标进入图片,图片自动避开到另一个地方
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class LayoutTest1 extends JFrame implements MouseListener{
private JPanel jpl = new JPanel();
private Icon ico = new ImageIcon("img.jpg");
private JLabel jlb = new JLabel(ico);
public LayoutTest1(){
jlb.addMouseListener(this);
jpl.setLayout(null);
jlb.setLocation(300,200);
jlb.setSize(ico.getIconWidth(),ico.getIconHeight());
jpl.add(jlb); this.add(jpl);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(800,600);
this.setVisible(true);
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
int X = (int)(Math.random() * 800);
int Y = (int)(Math.random() * 600);
jlb.setLocation(X,Y);
}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public static void main (String[] args) {
new LayoutTest1();
}
}
2、界面上一副图片,鼠标可以将图片从一个地方拖到另一个地方
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class LayoutTest1 extends JFrame implements MouseMotionListener {
private JPanel jpl = new JPanel();
private Icon ico = new ImageIcon("img.jpg");
private JLabel jlb = new JLabel(ico);
public LayoutTest1(){
this.addMouseMotionListener(this);
jpl.setLayout(null);
jlb.setLocation(300,200);
jlb.setSize(ico.getIconWidth(),ico.getIconHeight());
jpl.add(jlb); this.add(jpl);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(800,600);
this.setVisible(true);
}
public void mouseDragged(MouseEvent e){
int X = e.getX(); int Y = e.getY();
jlb.setLocation(X,Y);
}
public void mouseMoved(MouseEvent e){}
public static void main (String[] args) {
new LayoutTest1();
}
}
3、界面上一副图片,通过键盘上下左右键控制其移动
KeyListener
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class LayoutTest1 extends JFrame implements KeyListener {
private JPanel jpl = new JPanel();
private Icon ico = new ImageIcon("img.jpg");
private JLabel jlb = new JLabel(ico);
public LayoutTest1(){
this.addKeyListener(this);
jpl.setLayout(null);
jlb.setLocation(300,200);
jlb.setSize(ico.getIconWidth(),ico.getIconHeight());
jpl.add(jlb); this.add(jpl);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(800,600);
this.setVisible(true);
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
int X = jlb.getX(); int Y = jlb.getY();
if(code==KeyEvent.VK_UP){
Y-=ico.getIconHeight();
}else if(code==KeyEvent.VK_DOWN){
Y+=ico.getIconHeight();
}else if(code==KeyEvent.VK_LEFT){
X-=ico.getIconWidth();
}else if(code==KeyEvent.VK_RIGHT){
X+=ico.getIconWidth();
}
jlb.setLocation(X,Y);
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
public static void main (String[] args) {
new LayoutTest1();
}
}
绘图
绘图的前提
-
画架:JFrame
-
画布:JPanel
-
画笔:??
-
现场编程案例:在界面上放置一个画布
-
import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel{ public void paint(Graphics g){ System.out.println("Hello"); } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } }
-
基本结构:编写画布(JPanel子类),放置在JFrame上
画笔
-
JPanel有一个paint函数,函数中包含画笔
-
public void paint(Graphics g)
- 该函数中的参数,可以当成画笔使用
- 该函数在界面刷新时自动调用
- 绘图功能,写在paint函数中,用Graphics作为画笔
-
Graphics有drawXXX和fillXXX函数绘图;setColor函数设置颜色
-
案例:界面上绘制椭圆和线段,用不同颜色
-
import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel{ public void paint(Graphics g){ g.setColor(Color.red); g.drawLine(100,100,200,300); g.setColor(Color.blue); g.fillOval(100,200,200,100); } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } }
-
界面手工刷新:调用paint
-
用画布的repaint函数调用paint
-
案例:界面上不断出现随机位置,随机颜色,随机大小的椭圆
-
import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel implements Runnable{ public MyCanvas(){ new Thread(this).start(); } public void paint(Graphics g){ Graphics2D g2d = (Graphics2D)g; g2d.setColor(new Color((int)(Math.random()*256), (int)(Math.random()*256), (int)(Math.random()*256))); int X = (int)(Math.random()*this.getWidth()); int Y = (int)(Math.random()*this.getHeight()); int W = (int)(Math.random()*100); int H = (int)(Math.random()*100); g2d.fillOval(X,Y,W,H); } public void run(){ while(true){ try { Thread.sleep(100); } catch(Exception ex){} this.repaint(); } } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } } 2 import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel implements Runnable{ public MyCanvas(){ new Thread(this).start(); } public void paint(Graphics g){ Graphics2D g2d = (Graphics2D)g; g2d.setStroke(new BasicStroke(10)); g2d.setColor(new Color((int)(Math.random()*256), (int)(Math.random()*256), (int)(Math.random()*256))); int X = (int)(Math.random()*this.getWidth()); int Y = (int)(Math.random()*this.getHeight()); int W = (int)(Math.random()*100); int H = (int)(Math.random()*100); g2d.drawOval(X,Y,W,H); } public void run(){ while(true){ try { Thread.sleep(100); } catch(Exception ex){} this.repaint(); } } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } }
画笔Graphics升级版:Graphics2D
- 可以将Graphics对象直接转成Graphics2D使用
绘制图像
-
使用画笔的drawImage函数
-
案例:将img.jpg绘制在界面上
-
直接绘制图像
- drawImage(Image img,int x,int y, ImageObserver observer)
-
案例:将img.jpg缩放绘制在界面上
import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel { Image img = Toolkit.getDefaultToolkit().createImage("img.jpg"); public void paint(Graphics g){ g.drawImage(img,100,100,this); } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } } 2 import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel { Image img = Toolkit.getDefaultToolkit().createImage("img.jpg"); public void paint(Graphics g){ g.drawImage(img,100,100,this); g.drawImage(img,500,500, 200, 200, this); } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } }
-
缩放绘制图像
-
drawImage(Image img,int x,int y, int width,
int height,ImageObserver observer)- 案例:图像自动在界面上放大
-
import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel implements Runnable { int W = 0; int H = 0; Image img = Toolkit.getDefaultToolkit().createImage("img.jpg"); MyCanvas(){ new Thread(this).start(); } public void paint(Graphics g){ g.drawImage(img,100,100, W, H, this); } public void run(){ while(true){ W+=10; H+=8; repaint(); try{ Thread.sleep(100); } catch(Exception e){} } } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } }
-
裁剪绘制图像
-
import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel { Image img = Toolkit.getDefaultToolkit().createImage("img.jpg"); public void paint(Graphics g){ g.drawImage(img,0,0, this.getWidth(), this.getHeight(), 0, img.getHeight(this)/2, img.getWidth(this),img.getHeight(this) , this); } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } }
-
-
drawImage(Image img,int dx1,int dy1,
int dx2, int dy2,
int sx1, int sy1,
int sx2, int sy2,
ImageObserver observer) -
案例:将图像的下半部分绘制在界面,充满界面
- 旋转绘制图像
-
旋转绘制,实际上是画布旋转
-
使用Graphics2D的rotate函数
-
rotate(double theta, double x, double y)
-
绕圆心旋转某弧度
-
import javax.swing.*; import java.awt.*; class MyCanvas extends JPanel { Image img = Toolkit.getDefaultToolkit().createImage("img.jpg"); public void paint(Graphics g){ Graphics2D g2d = (Graphics2D)g; g2d.rotate(Math.PI/4, 100+img.getWidth(this)/2,100+img.getHeight(this)/2); g.drawImage(img,100,100,this); } } class PaintTest extends JFrame{ MyCanvas mc = new MyCanvas(); public PaintTest(){ this.add(mc); this.setSize(800,600); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new PaintTest(); } }
-
-
用TCP开发网络应用程序
前提知识
- 网络应用程序:支持网络通信的应用程序
- TCP:是一种常见的网络协议
基础概念
- 如何定位到网络上某台计算机?IP地址
- 通过网上邻居可以查看本机IP,如:172.17.10.144
- 如何定位同一计算机上的不同网络应用程序?端口
- 端口:英文:port 0-65535之间
- 系统为常见程序预设占用了端口,如HTTP:80
- 一般应用程序,建议用四位数做端口
- 网络应用程序本质:服务器(Server)和客户端(Client)
- 客户端连上服务器,信息通过服务器转发
网络应用程序编程过程
- 开发服务器程序,启动服务器程序,确定端口
- 开发客户端程序,通过服务器IP和端口,连上服务器
- 通信
今天内容在java.net包中
开发网络应用程序
- 案例:开发服务器和客户端程序,客户端连上服务器
- ServerSocket:启动服务器,接受客户端连接
- Socket:客户端连接服务器,并双方通信
客户端和服务器通信
- 用Socket通信
- 案例:客户端连上服务器,服务器发送一个欢迎信息;客户端收到后显示
- Socket:一般称为套接字
- 理解两个阻塞函数:accept readLine
import java.net.*;
import java.io.*;
class Server{
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888);
Socket s = ss.accept();
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("欢迎您连上服务器!");
}
}
///
import java.net.*;
import java.io.*;
class Client{
public static void main(String[] args) throws Exception {
Socket s = new Socket("172.17.10.144", 8888);
InputStream is = s.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg = br.readLine();
System.out.println(msg);
}
}
单客户端和服务器通信
-
案例:客户端和服务器端都有界面,界面下方有一个文本框,回车,信息能够发送给对方。双方都能够显示聊天信息
import java.net.*; import java.io.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class Server extends JFrame implements ActionListener,Runnable{ private JTextField jtf = new JTextField(); private JTextArea jta = new JTextArea(); private PrintStream ps = null; private BufferedReader br = null; private String nickName = null; Server() throws Exception{ this.add(jtf, BorderLayout.SOUTH); jtf.addActionListener(this); this.add(jta, BorderLayout.CENTER); jta.setBackground(Color.yellow); this.setSize(300,500); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); nickName = JOptionPane.showInputDialog("请您输入昵称"); ServerSocket ss = new ServerSocket(8888); Socket s = ss.accept(); ps = new PrintStream(s.getOutputStream()); br = new BufferedReader(new InputStreamReader(s.getInputStream())); new Thread(this).start(); } public void run(){ while(true){ try{ String msg = br.readLine(); jta.append(msg + "\n"); }catch(Exception e){} } } public void actionPerformed(ActionEvent e){ jta.append(nickName + "说" + jtf.getText() + "\n"); ps.println(nickName + "说" + jtf.getText()); } public static void main(String[] args) throws Exception { new Server(); } } // import java.net.*; import java.io.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; class Client extends JFrame implements ActionListener,Runnable{ private JTextField jtf = new JTextField(); private JTextArea jta = new JTextArea(); private PrintStream ps = null; private BufferedReader br = null; private String nickName = null; Client() throws Exception{ this.add(jtf, BorderLayout.SOUTH); jtf.addActionListener(this); this.add(jta, BorderLayout.CENTER); jta.setBackground(Color.pink); this.setSize(400,300); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); nickName = JOptionPane.showInputDialog("请您输入昵称"); Socket s = new Socket("172.17.10.144", 8888); ps = new PrintStream(s.getOutputStream()); br = new BufferedReader(new InputStreamReader(s.getInputStream())); new Thread(this).start(); } public void run(){ while(true){ try{ String msg = br.readLine(); jta.append(msg + "\n"); }catch(Exception e){} } } public void actionPerformed(ActionEvent e){ jta.append(nickName + "说" + jtf.getText() + "\n"); ps.println(nickName + "说" + jtf.getText()); } public static void main(String[] args) throws Exception { new Client(); } }
-
案例:客户端和服务器端都有界面,服务器下方有一个文本框,回车,内容能够发送给客户端界面,并且掉下来
import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Server extends JFrame implements ActionListener{
private JTextField jtf = new JTextField();
private PrintStream ps = null;
private BufferedReader br = null;
Server() throws Exception{
this.add(jtf, BorderLayout.SOUTH); jtf.addActionListener(this);
this.setSize(300,500);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
ServerSocket ss = new ServerSocket(8888);
Socket s = ss.accept();
ps = new PrintStream(s.getOutputStream());
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
public void actionPerformed(ActionEvent e){
ps.println(jtf.getText());
}
public static void main(String[] args) throws Exception {
new Server();
}
}
//
import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Client extends JFrame implements Runnable{
private JLabel jlb = new JLabel();
private BufferedReader br = null;
Client() throws Exception{
this.setLayout(null);
jlb.setSize(80,60);
this.add(jlb); jlb.setFont(new Font("宋体",Font.BOLD,30));
this.setSize(400,800);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
Socket s = new Socket("172.17.10.144", 8888);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
new Thread(this).start();
}
public void run(){
while(true){
try{
String msg = br.readLine();
jlb.setText(msg);
jlb.setLocation(100,100);
new WordThread().start();
}catch(Exception e){}
}
}
class WordThread extends Thread{
public void run(){
while(true){
jlb.setLocation(100,jlb.getY()+10);
if(jlb.getY()>=800) { break; }
try{ Thread.sleep(100); } catch(Exception e){}
}
}
}
public static void main(String[] args) throws Exception {
new Client();
}
}
用TCP开发网络应用程序
复习
- java.net
- ServerSocket accept函数
- Socket 得到输入输出流
- 启动服务器,客户端连上服务器,双方通过Socket通信
例题
服务器产生一个随机数,在客户端掉下。数字掉到客户端底部,重新进入下一局;客户端按下回车键,也重新进入下一局
- 服务器:读取客户端命令(NEXT);重新发送随机数
- 客户端:读取随机数;发送下一局命令给服务器端(NEXT)
import javax.swing.*;
import java.net.*;
import java.io.*;
class Server extends JFrame implements Runnable {
private BufferedReader br = null;
private PrintStream ps = null;
public Server() throws Exception {
this.setSize(200,300);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
ServerSocket ss = new ServerSocket(8888);
Socket s = ss.accept();
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
new Thread(this).start();
}
public void run(){
while(true){
try{
String msg = br.readLine();
if(msg.equals("NEXT")){
String str = (int)(Math.random()*100) + "";
ps.println(str);
}
}catch(Exception e){}
}
}
public static void main(String[] args) throws Exception {
new Server();
}
}
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.KeyEvent;
class Client extends JFrame implements Runnable,KeyListener{
private JLabel jlb = new JLabel();
private BufferedReader br = null;
private PrintStream ps = null;
private boolean FLAG;
public Client() throws Exception {
this.addKeyListener(this);
this.setLayout(null); this.add(jlb);
jlb.setSize(100,50); jlb.setFont(new Font("黑体",Font.BOLD,20));
this.setSize(300,600);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
Socket s = new Socket("127.0.0.1",8888);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
new Thread(this).start();
ps.println("NEXT");
}
public void run(){
while(true){
try{
String str = br.readLine();
//放在JLabel里面,并且往下掉
jlb.setText(str);
jlb.setLocation(100,50);
FLAG = true;
while(FLAG){
try{Thread.sleep(100);}catch(Exception e){}
jlb.setLocation(jlb.getX(), jlb.getY()+10);
if(jlb.getY()>=this.getHeight()){
//下一局
ps.println("NEXT");
break;
}
}
}catch(Exception ex){}
}
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_ENTER){
FLAG = false;
ps.println("NEXT");
}
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public static void main(String[] args) throws Exception {
new Client();
}
}
多客户端连接服务器
- 多客户端连上服务器
- 案例:每个客户端连上,服务器都会有提示
- 多客户端通过服务器通信
- 案例:群聊程序:每个客户端底部有一个文本框,回车,发出消息;消息通过服务器转发给所有连上的客户端
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;
class Server extends JFrame implements Runnable{
private ServerSocket ss = null;
private ArrayList<ChatThread> users = new ArrayList<ChatThread>();
public Server() throws Exception {
this.setSize(200,300);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
ss = new ServerSocket(8888);
new Thread(this).start();
}
public void run(){
while(true){
try{
Socket s = ss.accept();
ChatThread ct = new ChatThread(s);
users.add(ct); ct.start();
}catch(Exception ex){}
}
}
class ChatThread extends Thread{
BufferedReader br = null;
PrintStream ps = null;
ChatThread(Socket s) throws Exception{
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
}
public void run(){
while(true){
try{
String msg = br.readLine();
//群发给所有在线客户端
for(ChatThread ct : users){
ct.ps.println(msg);
}
}catch(Exception e){}
}
}
}
public static void main(String[] args) throws Exception {
new Server();
}
}
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
class Client extends JFrame implements Runnable ,ActionListener{
private JTextField jtf = new JTextField();
private JTextArea jta = new JTextArea();
private BufferedReader br = null;
private PrintStream ps = null;
private String nickName = null;
public Client() throws Exception {
this.add(jtf, BorderLayout.SOUTH); jtf.setFont(new Font("宋体",Font.BOLD,30));
this.add(jta, BorderLayout.CENTER); jta.setFont(new Font("楷体",Font.BOLD,20));
jtf.addActionListener(this);
this.setSize(300,600);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
nickName = JOptionPane.showInputDialog("请您输入昵称");
Socket s = new Socket("127.0.0.1",8888);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
new Thread(this).start();
}
public void run(){
while(true){
try{
String msg = br.readLine();
jta.append(msg + "\n");
}catch(Exception e){}
}
}
public void actionPerformed(ActionEvent e){
ps.println(nickName + "说:" + jtf.getText());
}
public static void main(String[] args) throws Exception {
new Client();
}
}
反射机制
- 反射:Reflection
- 也叫作反省机制
2、要点
- 类:Class,通过字符串载入一个类,并实例化
- 类:java.lang.reflect.Field,通过字符串获取某个对象中的public成员变量
- 类:java.lang.reflect.Method,通过字符串获取某个对象中的成员函数,并调用
1
class Customer{
public Customer(){
System.out.println("Customer构造函数");
}
public void fun(){
System.out.println("Customer.fun调用");
}
}
class Main{
public static void main (String[] args) {
String className = "Customer"; //模拟从文本文件中读入字符串
Customer c = new Customer();
}
}
class Student{
public Student(){
System.out.println("Student构造函数");
}
public void show(){
System.out.println("Student.show调用");
}
}
2
import java.io.*;
class Customer{
public Customer(){
System.out.println("Customer构造函数");
}
public void fun(){
System.out.println("Customer.fun调用");
}
}
class Main{
public static void main (String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("conf.txt"));
String className = br.readLine();
Class c = Class.forName(className);
c.newInstance();
}
}
class Student{
public Student(){
System.out.println("Student构造函数");
}
public void show(){
System.out.println("Student.show调用");
}
}
3
import java.lang.reflect.*;
class Customer{
public int i = 5;
public Customer(){
System.out.println("Customer构造函数");
}
public void fun(){
System.out.println("Customer.fun调用");
}
public void fun2(String s1, String s2){
System.out.println(s2 + "->" + s1);
}
}
class Main{
public static void main (String[] args) throws Exception {
String className = "Customer";
Class c = Class.forName(className);
Object obj = c.newInstance();
Field f = c.getField("i");
System.out.println(f.get(obj));
Method m = c.getMethod("fun",new Class[]{});
m.invoke(obj, new Object[]{});
Method m2 = c.getMethod("fun2",new Class[]{Class.forName("java.lang.String"),
Class.forName("java.lang.String")});
m2.invoke(obj, new Object[]{"123","456"});
/* Customer c = new Customer();
* System.out.println(c.i);
* c.fun();
**/
}
}
Java课程思维导图
Java语言基本语法
-
Java语言基本特点、编程规范
-
Java语言变量定义、变量运算、程序逻辑
-
Java语言中的数组定义和使用
面向对象基本概念
- 类:如何定义
- 对象:如何实例化,对象的引用性质
- 成员变量:如何使用成员变量
- 成员函数:如何定义和使用成员函数
- 构造函数:定义、性质、this关键字
- 函数重载:三大条件
- 静态变量:如何定义,如何访问,有何性质
- 静态函数:如何定义,如何访问,有何性质(只能访问静态成员)
面向对象基本特征
- 封装:package,import,public类,成员四个访问权限
- 继承:extends,继承的性质;覆盖,覆盖的性质和要求
super关键词 - 多态性:父类引用指向子类对象(了解其性质)
- 抽象类、接口:掌握抽象函数及其性质,抽象类定义及其性质;接口定义及其性质;抽象类和接口的区别
- final关键字:final变量、final函数、final类
Java语言的基本功能
- Java异常处理
- try、catch、finally的作用和搭配方式
- try-catch-finally结构的运行模式
- 常见异常
- throw和throws的使用场合
Java常用API
- Math类,给定函数,能使用
- String、StringBuffer,字符串常见功能,如得到字符、字符串长度等
- List、Set、Map的含义和区别
Java多线程开发
- 两种开发方式
- 线程启动
JavaIO操作
- 文件类、文件输入流、文件输出流各自名称和作用
- BufferedReader和PrintStream的定义和使用
Java应用开发
-用Swing开发GUI程序
-
常见界面、面板、控件、颜色、字体等对应的类及其所在包
-
Java事件处理
- 事件处理三要素,常见事件对应的接口
-
Java界面布局管理
- 流式布局、边界布局、网格布局对应的类及其特点
-
Java网络编程
-
ServerSocket、Socket的定义和作用
Java语言与系统设计课程思维导图
模块 | 内容 | 要点 |
---|---|---|
Java 语言基本语法 | Java特点 | 1、跨平台;2、运行的基本原理(代码用java文件,可执行文件是.class);3、语法和C基本相同,没有指针;程序入口是main函数** |
Java****语法 | 1**、变量、数据类型:float和long定义比较特殊;各种数据类型的精度顺序,高精度不能直接赋值给低精度;不能用0和非0表示真假;变量的定义必须掌握;字符数据类型有转义字符,用 ?表示** 2**、运算:算术运算:+ - * / % += -= *= /= ++ – ; 关系运算:> < >= <= == !=;逻辑运算:&& || !** 3**、流程:选择:if语句、switch-case;循环:for、while、do-while 配合 break、continue** 4**、数组:一维数组和二维数组的定义方式以及其特点(数组名称也是一个引用;二维数组实际上是一维数组的组合)** | |
面向对象基本概念 | 类和对象 | 类的定义(要会编程);由类来实例化对象原理;对象名的引用性质(理解对象名重新指向另一个对象的情况) |
成员变量和成员函数 | 成员变量和成员函数的定义;通过对象访问成员变量成员函数(.号);成员函数参数传递时的值传递和引用传递的区别(需要能够分析实例) | |
特殊的成员变量和成员函数 | 1**、构造函数:定义方式、调用特点、垃圾收集机制** 2**、函数重载:三个条件满足其一即可** 3**、静态变量:定义方式、性质特点、如何调用(类名.或者对象名.来调用)** 4**、静态函数:定义方式(和静态变量类似)、性质特点(静态函数只能访问静态成员和函数中的局部变量)、如何调用(类名.或者对象名.来调用)** 常见概念的英文形式必须要掌握 需要能够进行基本的编程 | |
面向对象基本特征 | 封装 | 1**、包:定义包(注意包的嵌套关系);导入包中的类** 2**、类:public类(定义方式、特点);普通类(定义方式、特点)** 3**、成员:四个访问控制符:public、protected、默认、private** 理解它们的具体权限 需要能够进行基本的编程 |
继承 | 1**、如何实现继承(extends)?Java继承的特点(只能使用继承的非private成员、Java不支持多重继承)** 2**、覆盖:如何编程才算覆盖(子类定义成员和父类名称、返回类类型、参数皆相同)?覆盖有什么特点(子类对象调用时,直接调用子类成员)和要求(不允许减小子类成员的权限)?** 3**、父类构造函数的初始化(子类实例化时,会自动调用父类的构造函数,如果父类构造函数带参数,必须用super(参数列表)初始化父类对象,代码写在子类构造函数的第1句)** 4**、this和super的用法和意义** | |
多态性 | 1**、多态性的定义:父类引用指向子类对象** Dialog d = new FontDialog(); 2**、性质:该引用调用重写成员时,调用的是子类成员** | |
抽象类、接口等其他内容 | 1**、抽象类如何定义?含有抽象函数的类,类前用abstract修饰** 2**、抽象类有何性质?不能被实例化;可以有普通函数;里面抽象函数必须被重写(除非子类也是抽象类)** 3**、接口如何定义?和抽象类有何区别?interface,用implements来实现。可以实现多个接口;接口中所有的函数都是抽象函数,并且是public;所有变量都是public的静态的final的变量(常量)** 4**、Object类:Java中所有类的最高父类** 5**、final关键字:final变量、final函数、final类特点** | |
Java****语言基本功能 | 异常 | 1**、try、catch、finally:匹配规则try(1)-catch(1…)-finally(0,1);程序运行的逻辑;了解Java中常见异常类和异常原因的对应(代码预测):NullPointerException、NumberFormatException、IOException等等** 2**、throw、throws:掌握其使用的位置** |
多线程 | 1**、定义线程(能写代码):继承Thread、实现Runnable** Thread.sleep(XX);知道其用法 2、调用线程:启动线程:继承Thread、实现Runnable两类有不同的启动方法 3**、控制线程:暂停和继续** | |
基本API | 1**、java.lang:Math重点掌握随机数;String重点掌握字符串长度、字符串按位置访问函数;StringBuffer掌握和String的区别;基本数据类型的包装类掌握字符串和数值的互相转换** 以上需要会编程 2**、java.util:变长数组:List系列(子类)、Set系列(子类)、Map系列(子类);掌握其区别;需要能够用它们解决实际问题(写伪代码)** | |
IO | 1**、java.io包** 2**、File、FileInputStream、FileOutputStream、BufferedReader、PrintStream、RandomAccessFile各自的功能(不编程)** | |
Java****语言界面开发 | 界面和控件 | javax.swing: 界面和控件,常见的必须知道意义 **java.awt:**颜色和字体 |
布局 | java.awt: FlowLayout/BorderLayout/GridLayout****区别 | |
Java****事件开发 | 事件开发 | java.awt.event****包,按钮点击等简单事件用什么来监听,发出什么类型事件? |
Java****绘图 | Graphics**、paint函数作用** | |
repaint****函数作用 | ||
Java****网络编程 | 基本概念 | IP****地址、端口各自区别;服务器、客户端的区别 |
具体实现 | java.net ServerSocket\Socket****各自作用;ServerSocket的accept函数的意义。 |