550 likes | 720 Views
第 4 ç« ç¼–å†™ç±». Java Software Solution Foundations Program Design. 类和对象. 对象表示现实世界ä¸æŸä¸ªå…·ä½“的事物 抽象是从特定的实例ä¸æŠ½å–å…±åŒçš„性质以形æˆä¸€èˆ¬åŒ–概念的过程 对象具有两方é¢çš„å«ä¹‰ï¼š 在现实世界ä¸ï¼š 是客观世界ä¸çš„一个实体 在计算机世界ä¸ï¼š 是一个å¯æ ‡è¯†çš„å˜å‚¨åŒºåŸŸ. 类和对象. å°è£…的实体 = æ•°æ® + 方法. æ•°æ®æˆ–å˜é‡. 类是具有共åŒå±žæ€§å’Œè¡Œä¸ºçš„对象的抽象 ç±»å¯ä»¥å®šä¹‰ä¸ºæ•°æ®å’Œæ–¹æ³•çš„é›†åˆ ç±»ä¹Ÿç§°ä¸ºæ¨¡æ¿ï¼Œå› 为它们æ供了对象的基本框架. ç±». 方法. 实例化. 抽象.
E N D
第4章 编写类 Java Software Solution Foundations Program Design
类和对象 • 对象表示现实世界中某个具体的事物 • 抽象是从特定的实例中抽取共同的性质以形成一般化概念的过程 • 对象具有两方面的含义: • 在现实世界中: • 是客观世界中的一个实体 • 在计算机世界中: • 是一个可标识的存储区域
类和对象 封装的实体=数据+方法 数据或变量 • 类是具有共同属性和行为的对象的抽象 • 类可以定义为数据和方法的集合 • 类也称为模板,因为它们提供了对象的基本框架 类 方法 实例化 抽象 属性或状态 对象 操作或行为
在类中,属性是通过成员变量体现的,而操作是用成员函数(又称为方法)实现的。在类中,属性是通过成员变量体现的,而操作是用成员函数(又称为方法)实现的。 创建类 Java中定义类的通用格式: class name { type variable1; … type variableN; type methodname1(parameter-list){ //方法体 } … type methodnameN(parameter-list){ //方法体 } } 成员变量(对象属性) 成员方法 (对象行为或操作)
发往某个对象的消息对应于一个方法调用。作为对消息的响应,对象将执行一个类似于过程体的方法。方法是包含在类中的函数。发往某个对象的消息对应于一个方法调用。作为对消息的响应,对象将执行一个类似于过程体的方法。方法是包含在类中的函数。 方法名称 修饰符,可选 返回类型 参数列表,可选 定义方法 • 定义方法的一般格式: [access] type methodname1([parameter-list]){ //方法体 } • 举例: • public void setdate(int day, int month, int year){ • day=23; month=7; year=2003; • } 示例2FruitDemo.java
当对象作为函数参数时,在函数中只能改变该对象的状态,但不能改变该对象的引用当对象作为函数参数时,在函数中只能改变该对象的状态,但不能改变该对象的引用 obj1 obj2 x x y y Day Day 2003,7,23 2002,5,30 对象作为参数 void swapobj(Day x,Day y){ Day temp=y; y=x; x=temp; } class Test{ int a,b; Test(int i,int j) { a=i; b=j; } //可以在函数中改变对象状态 void change(Test obj) { obj.a=50; obj.b=40; } } 引用本身 按值传递 改变对象状态 调用swapobj(obj1,obj2)
关键字 this 与对象关联 • 它用于指示当前对象 this引用 public class PassTest { int x; PassTest(int x) { this.x=x; } public void passingValue(){ System.out.println(“x 等于" +x); } public static void main(String args[]) { PassTest test = new PassTest(10); test.passingValue(); } } 指明此对象的变量 x 应赋值为通过构造函数传递的自变量 x 的值。
简单访问控制 - private 和 public • public 声明的数据成员和成员函数可从类外部的任何地方访问。 • 而private 数据将被隐藏,在类外不可见,这就实现了数据封装的思想。 • 要从类外操纵private 成员,只能通过类的public或protected成员来实现。
方法重载(overloading) • 方法重载是Java实现面向对象的多态性机制的一种方式 • 同一个类中多个方法有相同的名字,不同的参数列表,这种情况称为方法重载。 • 返回类型不同并不足以构成方法重载。 • 当重载方法被调用时,编译器根据参数的类型和数量来确定实际调用哪个重载方法的版本。
方法重载示例 class Calculation { public void add( int a, int b) { int c = a + b; System.out.println("两个整数相加得 "+ c); } public void add( float a, float b){ float c = a + b; System.out.println("两个浮点数相加得"+c); } public void add( String a, String b) { String c = a + b; System.out.println("两个字符串相加得 "+ c); } } class CalculationDemo { public static void main(String args[]) { Calculation c = new Calculation(); c.add(10,20); c.add(40.0F, 35.65F); c.add("早上", "好"); } } 编译器决定调用版本
构造函数 • 构造函数名称与类名称相同 • 构造函数没有返回类型 • 其任务是在创建对象时初始化其内部状态 class Fruit { boolean seedLess; boolean seasonal; float price; Fruit(boolean seed, boolean season, float p) { seedLess = seed; seasonal = season; price = p; } }
当创建一个类时,只是创建了一种新的数据类型。对象是类的一个实例。当创建一个类时,只是创建了一种新的数据类型。对象是类的一个实例。 创建对象 • 使用下列语法可创建对象: new 构造函数 • 关键字 new 通常称为创建运算符,用于分配对象内存,并将该内存初始化为缺省值。 • 一旦 new 完成分配和初始化内存,它就将调用构造函数来执行对象初始化。 class FruitDemo { public static void main(String args[]){ Fruit f = new Fruit(true,false,50.0F); } } 创建对象
缺省初始值 • Java 保证了在任何代码使用该内存之前,已至少将内存初始化为可预知的缺省值
重载构造函数 • Java 为每一个类自动提供缺省构造函数 • 缺省构造函数将成员变量的值初始化为缺省值 • 一旦创建了自己的构造函数,缺省的构造函数将不复存在。 • 重载构造函数提供了一组创建对象的方式,可以根据需要决定是否带初始参数。 public class constructOverload { int x; constructOverload() { x=0; System.out.println("不带参数的构造函数"); } constructOverload(int x){ this.x=x; System.out.println("带一个参数的构造函数"); } }
继承是面向对象编程技术的一块基石,它允许创建分等级层次的类。运用继承,可以创建一个通用类定义一系列一般特性。该类可以被更具体的类继承继承是面向对象编程技术的一块基石,它允许创建分等级层次的类。运用继承,可以创建一个通用类定义一系列一般特性。该类可以被更具体的类继承 Emoloyee类: name sex Officer类: empClass vehicle Worker类: category dressAllowance 继承 • 被继承的类称为父类 • 继承父类的类称为子类 • 执行继承时,子类将获得父类的属性,并具有自身特有的属性。 职员类,具 有姓名和性 别两个属性 工人类,继承了父 类的姓名和性别属 性外还包含类别和 是否有服装津贴属性 主任类,还包含 级别和是否配备 交通工具属性
extends关键字 • extends关键字用于继承类。 • 声明一个继承父类的类的通常形式如下: class subclass-name extends superclass-name { //类体 } • 没有extends,默认父类为Object • 只能有一个父类,即单继承 • 子类继承父类的全部成员 注意
super关键字 • super关键字用来解决如何直接访问或初始化从父类继承来的属性。 • super有两种通用形式:调用父类的构造函数、用来访问被子类的成员覆盖的父类成员。 • 它用在对象的构造函数中,将构造细节通过继承链往上传递。 • super()必须是在子类构造函数中的第一个执行语句。
继承示例 class InheDemo { public static void main(String args[]) { Worker w = new Worker("M.John",'M','B',true); System.out.println("工人信息"); System.out.println("姓名: "+w.getName()); System.out.println("性别:"+w.getSex()); System.out.println("类别: "+w.getCategory()); if(w.getAll()) System.out.println("提供服装津贴"); else System.out.println(“未提供服装津贴”); } } class Employee { String name; //姓名 char sex; //性别 Employee(String n, char s){ name = n; sex = s; } public String getName() { return name; } public char getSex(){ return sex;}} class Worker extends Employee { char category;//类别 boolean dressAllowance; //是否提供服装津贴 Worker(String n,char s,char c,boolean d){ super(n,s); category = c; dressAllowance = d; } public char getCategory(){return category;} public boolean getAll(){ return dressAllowance; } }
instanceof 测试第一个参数的运行时类型是否为与第二个参数兼容的赋值。 instanceof class Student {} class Graduate extends Student {} class UndergraduateStudent extends Student {} public class st { public static void main(String []args) { UndergraduateStudent s1 = new UndergraduateStudent(); Graduate s2=new Graduate(); Student x; x=s1; if (x instanceof UndergraduateStudent) System.out.println(“x是UndergraduateStudent类的实例。”); else System.out.println(“x是Graduate类的实例。”); } } x在运行时指向s1,所以if语句条件返回true
类型转换 • 执行自动类型转换需要两个条件: • 接受转换的两种类型是兼容的 • 目的类型数的范围比源类型的大 • 强制类型转换语句的通用格式如下: (目标类型)value UndergraduateStudent s1 = new UndergraduateStudent(); Graduate s2=new Graduate(); Student x; x=s1; Graduate s3=new Graduate(); if (x instanceof Graduate) s3= (Graduate)x; 注意:从父类到子类的转换,建议在转换前判断父类是否指向子类的对象
Object 类 • Object类是类体系结构的根 • Java 系统中的每个类都是 Object 类直接或间接的子类 • Object 类包括在 java.lang 包中 • 此类定义了所有对象都具备的基本状态和行为 • 可以用类型为Object的变量来引用任意类型的对象
equals() • 用于比较两个对象是否相等,相等返回 true • Object 类中提供的 equals 方法使用恒等函数来确定对象是否相等 • Object类中实现的equals方法只能用来判断两个不同的对象是否指向同一个内存区域 • 子类一般通过覆盖Object的equals方法实现有意义的测试,可以实现:若同一类型的两个不同对象包含相同的信息即返回true Integer one = new Integer(1); Integer anotherOne = new Integer(1); if (one.equals(anotherOne)) System.out.println("对象相等");
toString() • toString 用于返回对象的字符串表示。 • 建议所有子类都覆盖此方法。 • 使用“+”运算符将对象同一个字符串连接,Java编译器会自动调用toString方法,获取对象的字符串表现形式。 Derived d = new Derived(); System.out.println("Derived 的toString() :" + d); 自动调用d.toString方法,获取对象的字符串表示形式
方法覆盖(override) • 方法覆盖是Java实现多态性机制的另一种方式。 • 在类层次结构中,如果子类中的一个方法与父类中的方法有相同的方法名并具有相同数量和类型的参数列表,这种情况称为方法覆盖。 • 当一个覆盖方法通过父类引用被调用,Java根据当前被引用对象的类型来决定执行哪个版本的方法。 • 可以通过super关键字调用直属父类中被覆盖的方法版本。
方法覆盖示例 class SuperClass { int a; SuperClass(){ a = 10; } public void printA(){System.out.println("父类中a ="+a);} } class SubClass extends SuperClass { int a; SubClass(int a){ this.a = a; } public void printA(){ System.out.println("子类中a = "+a); } } public class OverrideDemo { public static void main(String args[]) { SuperClass s1 = new SubClass(10); s1.printA(); } } 将调用子类的printA方法
包 • 在Java中,包主要有以下用途 : • 包允许将类组合成较小的单元 • 有助于避免命名冲突 • 包允许在更广的范围内保护类、数据和方法 • 包可以是类、接口和子包的集合
创建包 • package mypackage ; • public class Calculate • { • public int add(int x, int y) • { • return( x + y ) ; • } • } 在Java 中,包用下面的方式来创建包: packagepackage_name; calculate mypackage
创建包(续) • 当创建一个包时,应注意任何创建包的语句应放在导入包的语句前 • 创建包的时候,必须在import语句之前编写包声明 • 如果需要从外部访问包的成员类,则要将其定义为public 正确使用格式 错误使用格式 import java . io; package mypackage ; package mypackage ; import java . io;
Calculate . Class 编译包——将.class放在指定的包下 javac-dc:\ JavaProgs Calculate.java 用-d选项,在命令行下执行上面的语句,编译器将在您当前的文件夹(假设为 JavaProgs)下产生一个文件夹 mypackage 并把 Calculate.class存放在该文件夹下 JavaProgs mypackage 包用文件夹来表示,实质上就是一个路径
使用包 Calculate 类 计算两个数之和的方法: public int add(int x, int y) 其他用于计算的方法: • 为了计算两个整数之和,我们不需要专门写计算和的代码 • 我们可导入包 “mypackage”,并使用其中的 public int add(int x, int y)方法来计算
使用包中的成员 • 直接引用 如果使用了不同包中的类,而未使用该包的导入语句,则需要使用带有包名称的类名称 class Demo{ mypackage.Calculate calc=new mypackage.Calculate(); …… } • 导入包中的类 • 导入包 // import mypackage. *; import mypackage.Calculate; class Demo{ Calculate calc=new Calculate(); …… }
使用包 • 归纳几种使用包的方式: • 导入要使用的类 • import mypackage.Calculate; • 导入整个包 • import mypackage.*; • 直接 引用 • mypackage.Calculate calc=new mypackage.Calculate(); 推荐使用前两种方式
编译使用包的.java文件——带参数classpath • javac-classpathc:\ JavaProgs PackageDemo.java • 上述编译命令显式指定编译器按照classpath的内容搜索编译资源 • classpath中各项条目路径的顺序是非常重要的,JVM按照所提及的顺序搜索类路径中的条目寻找类,直到找到一个类为止
编译使用包的.java文件——classpath环境变量 • 如果不想在编译命令中显式指定classpath参数,可以设置classpath环境变量 • classpath变量的设置方法: • 控制面板-系统-高级-环境变量-系统变量-修改或新增classpath变量 • Dos命令:set classpath = path1; path2 [;…] • path为包的存放路径,注意: path中应包含当前路径. • 如: set classpath = .;d:\java;e:\ppp\xxx • 这样的话,编译使用包的.java文件时就无需带classpath参数。 javacPackageDemo.java • 执行 • Java.exe –cp . PackageDemo
包的总结 • 创建包 package mypackage; • 访问 Java 包成员 mypackage.My_Class • 导入包 • import package_name.*; • 导入子包 • import package_name.*;
AWT概述 通过 AWT ( 重量级组件) 创建 GUI java.awt包 AWT包含内容 容器 包含 AWT容器组件 组件 以图形表示的对象允许用户交互 布局管理器 定义 GUI 组件的位置 图形和绘制方法 使用 AWT图形方法相对于窗口绘制图形 字体 创建并构造用于选择新字体的对象 事件 用于用户和系统交互
容器 包含 Swing 组件 组件 以图形表示的对象允许用户交互 可改变的外观 可更换图形界面的风格 Java2D图形绘制 使用Java2D绘制图形 Swing 通过 Swing (轻量级组件,纯Java组件) 创建 GUI Javax.swing 包 Swing 包含内容
Swing 轻量级组件 可改变的外观 MVC 结构 性能更稳定 优点 Swing (与AWT相比)
Swing容器组件 Swing应用程序 顶层容器(每个应用 程序中至少有一个) 主窗口 主要显示区域包含 GUI中的可视组件 内容面板 创建顶层容器 创建容器 设置容器大小 (对框架及面板而言) 设置容器可见度 (对框架及面板而言)
Swing容器组件 javax.swing包 常见容器 JFrame JScrollPane JPanel 1. 扩展 java.awt.Frame类 2. 用于在 Swing程序中创建窗口 3. 包含边框、标题和用于关闭和图标化窗口的按钮 1. 中间容器 2. 用于将较小的轻量级组件组合在一起 3. 与内容窗格相似,面板在默认情况下不透明 • 管理视区、滚动条及可选的行和列的标题视区
Swing容器组件 javax.swing包 常用的顶层容器 JFrame JScrollPane JPanel 1. 扩展 java.awt.Frame类 2. 用于在 Swing程序中创建窗口 3. 包含边框、标题和用于关闭和图标化窗口的按钮 1. 中间容器 2. 用于将较小的轻量级组件组合在一起 3. 与内容窗格相似,面板在默认情况下不透明 1.管理视区、滚动条及可选的行和列的标题视区
Swing GUI 组件 JTexField JComboBox JLabel JCheckBox JTexArea JButton JRadioButton
组件和容器 GUI组件(component)是一个对象,代表一个用于显示信息或允许用户以某种方式与程序进行交互的屏幕元素。 容器(container)是一个保存和组织其他组件的特殊组件,框架和面板就是两种容器 关键概念:容器是一个保存和组织其他组件的特殊GUI组件。
JLabel JLabel
JTextField JTextField
JTextArea JTextArea
框架和面板 框架(frame)是一个容器,用户显示基于GUI的Java应用程序界面。 面板(panel)也是一个容器,面板自身不能独立显示。 关键概念:框架作为一个独立窗口显示,而面板则只能作为其他容器的组成部分显示。
布局管理器 • 用户界面上的屏幕组件可以按照一定的格式布局 例如水平排列,或按网格方式排列 • 布局管理器类是一组类,它 • 实现 java.AWT.LayoutManager接口 • 帮助在容器中放置组件 • Java 中可用的各种布局如下: • BorderLayout • FlowLayout • GridLayout
BorderLayout North 上边的组件 左 边 的 组 件 右 边 的 组 件 CENTER West East 容器 下边的组件 South