第22 章 : 泛型
96 泛型问题引出
JDK >= 1.5
主要为了解决 ClassCastException
举例:
要描述一个坐标类,允许存放以下坐标数据类型
整型 x = 10, y = 20
浮点型 x = 10.1, y = 20.2
字符串型 x = 东经 10 度 , y = 北纬 20 度
可以使用Object,不过会出现转型操作
整型: 基本数据类型 -> Integer包装类 -> 自动向上转型为Object
浮点型 :基本数据类型 -> Double包装类 -> 自动向上转转型为Object
字符串型 :String对象 -> 自动向上转转型为Object
class Point{ private Object x ; private Object y ; public Point(Object x, Object y){ this.x = x ; this.y = y ; } public void setX(Object x){ this.x = x ; } public void setY(Object y){ this.y = y ; } public Object getX(){ return this.x ; } public Object getY(){ return this.y ; } @Override public String toString(){ return "Point("+ this.x + ", " + this.y + ")" ; } } class Demo{ public static void main(String[] args) { Point p1 = new Point(1, 2); System.out.println(p1); // Point(1, 2) int x = (Integer)p1.getX() ; System.out.println(x); // 1 Point p2 = new Point(1.1, 2.2); System.out.println(p2); // Point(1.1, 2.2) // Object 不能约束传入的参数 Point p3 = new Point(10, "北纬20度"); System.out.println(p3); // Point(10, 北纬20度) } }
97 泛型基本定义
类中属性或方法的参数与返回值类型由对象实例化的时候动态决定
需要在类定义的时候明确的定义占位符(泛型标记)
实例化不设置泛型类型,默认使用Object
Point<Integer> p1 = new Point<Integer>(1, 2);
泛型的好处:
1、编译时检查类型,避免出现安全隐患
2、避免向下转型操作
泛型注意点:
1、只能使用引用类型,基本类型要使用包装类
2、JDK >=1.7开始可以简写
Point<Integer> p1 = new Point<>(1, 2);
使用泛型可以解决大部分的类对象强制转换处理
class Point<T>{ private T x ; private T y ; public Point(){} public Point(T x, T y){ this.x = x ; this.y = y ; } public void setX(T x){ this.x = x ; } public void setY(T y){ this.y = y ; } public T getX(){ return this.x ; } public T getY(){ return this.y ; } @Override public String toString(){ return "Point("+ this.x + ", " + this.y + ")" ; } } class Demo{ public static void main(String[] args) { Point<Integer> p1 = new Point<Integer>(1, 2); System.out.println(p1); // Point(1, 2) int x = (Integer)p1.getX() ; System.out.println(x); // 1 Point<Double> p2 = new Point<Double>(1.1, 2.2); System.out.println(p2); // Point(1.1, 2.2) Point<String> p3 = new Point<String>("东经30度", "北纬20度"); System.out.println(p3); // Point(10, 北纬20度) } }
98 泛型通配符
目前的泛型进行引用传递
class Message<T>{ private T content; public void setContent(T message){ this.content = message; } public T getContent(){ return this.content; } } class Demo{ public static void main(String[] args) { Message<String> message = new Message<>(); message.setContent("Hello Java"); showMessage(message); } // 只能接收Message<String> 对象 public static void showMessage(Message<String> message){ System.out.println(message.getContent()); // Hello Java } }
修改为通配符接收数据
public static void showMessage(Message<?> message) { System.out.println(message.getContent()); // Hello Java }
设置泛型范围
// 设置泛型上限 // ? extends 类 // 例如:只允许设置Number 或其子类 ? extends Number // 设置泛型下限 // ? super 类 // 例如:只能够使用String 或其父类 ? super String
public static void showMessage(Message<? extends Number> message) { System.out.println(message.getContent()); } public static void showMessage(Message<? super String> message) { System.out.println(message.getContent()); }
99 泛型接口
1、实现类继续使用泛型
interface IMessage<T>{ public void echo(T t); } class Messageimpl<S> implements IMessage<S> { public void echo(S t){ System.out.println(t); } } class Demo{ public static void main(String[] args) { Messageimpl<String> message = new Messageimpl<>(); message.echo("Hello"); // Hello } }
2、实现类不使用泛型
interface IMessage<T>{ public void echo(T t); } class Messageimpl implements IMessage<String> { public void echo(String t){ System.out.println(t); } } class Demo{ public static void main(String[] args) { Messageimpl message = new Messageimpl(); message.echo("Hello"); // Hello } }
100 泛型方法
泛型方法:泛型标记写到了方法上
泛型方法不一定非要出现在泛型类中
class Demo{ public static <T> T[] getArray(T ...args){ return args; } public static void main(String[] args) { Integer[] list = getArray(1, 2, 3); for(int x : list){ System.out.println(x); // 1 2 3 } } }
第23 章 : 包的定义及使用
101 包的定义
包 == 目录
“.”表示分隔子目录
package com.name.demo; public class Hello{}
编译后的.class文件需要保存到指定目录中
打包处理
$ javac -d . Hello.java
-d 表示要生成的目录,package定义的结构
. 表示当前所在目录
程序执行的时候一定要带着包执行程序
$ java com.name.demo.Hello
102 包的导入
直接编译,让java决定编译先后顺序
$ java -d . *.java
注意:
1、public class
类名必须与文件名保持一致
2、要被其他包所使用的类要加public
3、一般一个java文件只有一个class类
4、class
类名称可以与文件名不一致,可以提供多个类,会被编译为多个class文件
而且只能被本包所访问
包名必须采用小写字母定义
导入可以使用通配符 *
不表示全部加载,会根据需要加载
会出现引用不明确问题
使用的时候直接写完整路径
import com.name.demo; com.name.demo.Hello();
导包示例
Message.java
package com.name.demo ; public class Message{ public void printMessage(String message){ System.out.println(message); } }
Demo.java
import com.name.demo.Message ; class Demo{ public static void main(String[] args) { Message message = new Message(); message.printMessage("Hello Message") ; } }
打包执行
# 编译打包文件 $ javac -d . *.java # 执行 $ java Demo Hello Message
文件目录
├── Demo.class ├── Demo.java ├── Message.java └── com └── name └── demo └── Message.class
103 静态导入
JDK >=1.5
import static com.name.demo.Demo.* ;
Message.java
package com.name.demo ; public class Message{ public static void echoMessage(String message){ System.out.println(message); } }
Demo.java
import static com.name.demo.Message.* ; class Demo{ public static void main(String[] args) { echoMessage("Hello Message") ; } }
104 生成jar文件
jar文件: 管理class文件
步骤:
打包编译 javac -d . Message.java
打包jar jar -cvf name.jar com
-c create 创建文件
-v verbose 详细输出
-f file 要生成的jar文件
rar打开jar文件
每个.jar文件都是独立的程序路径,必须通过CLASSPATH配置
windows: 以分号分隔
$ SET CLASSPATH=.;d:\name.jar
Mac:以冒号分隔
$ export CLASSPATH=".:/root/name.jar"
JDK < 1.9
所有类的jar文件: rt.jar tools.jar
JDK >= 1.9 模块化设计
105 系统常用包
Java自身提供类库
第三方提供支持类库
java.lang String, Number, Object JDK 1.1自动导入
java.lang.reflect 反射机制
java.util 工具类,数据结构
java.io 输入输出
java.net 网络开发
java.sql 数据库编程
java.applet 嵌套网页执行
java.awt 图形界面GUI开发Windows位置
java.swing(JDK1.2)轻量级图形开发包
106 访问控制权限
面向对象三个特点:封装,继承,多态
访问控制权限
访问范围 private default protected public 同包同类 true true true true 同包不同类 true true true 不同包的子类 true true 不同包的所有类 true
参考选择
属性定义 private
方法定义 public
通过子类访问protected 属性
Message.java
package com.util.a ; public class Message{ protected String info = "message info"; }
TestMessage.java
package com.util.b ; import com.util.a.Message ; public class TestMessage extends Message{ public void showInfo(){ System.out.println(super.info); } }
Demo.java
import com.util.b.TestMessage ; public class Demo{ public static void main(String[] args) { new TestMessage().showInfo(); } }
第24 章 : UML图形
107 类图
UML统一建模语言: 利用图形化的形式来实现程序类关系的描述
三层结构表示
类名称 属性 方法
抽象类属性斜体abstract
属性格式:访问权限 属性名称: 属性类型
public +
protected #
private -
方法格式:访问权限 方法名称(): 返回值
画图工具
Rational Role
PowerDesigner
子类实现接口 三角和虚线
子类继承父类 三角和实线
108 时序图
描述代码的执行流程
109 用例图
描述程序执行分配
一般出现在项目设计过程
第25 章 : 单例设计模式
110 单例设计
单例设计模式:只允许提供一个实例对象
-饿汉式:系统加载就实例化
-懒汉式:第一次使用的时候实例化
多例设计模式
单例模式特点:
构造方法私有化,内部提供static方法获取实例化对象
饿汉式单例模式
class Singleton{ private static Singleton singleton = new Singleton(); // 构造函数私有化 private Singleton(){}; public static Singleton getInstance(){ return singleton ; } } class Demo{ public static void main(String[] args) { Singleton singleton = Singleton.getInstance(); } }
懒汉式单例模式
class Singleton{ private static Singleton singleton ; // 构造函数私有化 private Singleton(){}; public static Singleton getInstance(){ // 第一次使用实例化 if (singleton == null){ singleton = new Singleton(); } return singleton ; } }
111 多例设计
class Color{ private String title; private static final Color RED = new Color("红色"); private static final Color GREEN = new Color("绿色"); private static final Color BLUE = new Color("蓝色"); private Color(String title){ this.title = title ; }; public static Color getInstance(String color){ switch(color){ case "red" : return RED; case "green" : return GREEN; case "blue" : return BLUE; default: return null; } } @Override public String toString(){ return this.title; } } class Demo{ public static void main(String[] args) { Color red = Color.getInstance("red") ; System.out.println(red); } }
单例和多例都会提供一个静态获取实例化的方法
第26 章 : 枚举
112 定义枚举类
JDK >= 1.5
枚举主要用于定义有限个数对象的一种结构(多例设计)
枚举可以在程序编译时判断实例化对象是否存在
enum Color{ RED, GREEN, BLUE } class Demo{ public static void main(String[] args) { for(Color color : Color.values()){ System.out.println(color); } // RED GREEN BLUE } }
switch中对枚举类判断
enum Color{ RED, GREEN, BLUE } class Demo{ public static void main(String[] args) { Color color = Color.RED ; switch(color){ case RED : System.out.println("红色"); break; case GREEN : System.out.println("绿色"); break; case BLUE : System.out.println("蓝色"); break; default : System.out.println("default"); } // 红色 } }
113 Enum类
枚举本质是一个类
枚举中每一个对象序号都是根据枚举对象的定义顺序来决定的
enum Color{ RED, GREEN, BLUE } class Demo{ public static void main(String[] args) { for(Color color : Color.values()){ System.out.println(color.ordinal() + " - " + color.name()); } /** 0 - RED 1 - GREEN 2 - BLUE */ } }
enum和Enum区别
enum 是JDK 1.5之后提供的关键字,定义枚举类
Enum 是一个抽象类,关键字enum定义的类默认继承此类
114 定义枚举结构
枚举类本身属于多例设计模式
在枚举类中定义其他结构
// 枚举类 enum Color{ // 枚举对象要写在首行 RED("红色"), GREEN("绿色"), BLUE("蓝色") ; // 定义属性 private String title ; private Color(String title){ this.title = title ; } @Override public String toString(){ return this.title ; } } class Demo{ public static void main(String[] args) { for(Color color : Color.values()){ System.out.println(color.ordinal() + " - " + color.name() + " - " + color); } /** 0 - RED - 红色 1 - GREEN - 绿色 2 - BLUE - 蓝色 */ } }
枚举类中可以实现接口继承
interface Imessage{ public String getMessage(); } enum Color implements Imessage{ RED("红色"), GREEN("绿色"), BLUE("蓝色") ; private String title ; private Color(String title){ this.title = title ; } @Override public String toString(){ return this.title ; } public String getMessage(){ return this.title ; } } class Demo{ public static void main(String[] args) { Imessage message = Color.RED ; System.out.println(message.getMessage()); // 红色 } }
枚举类可以直接定义抽象方法,
并且要求每一个枚举对象都要独立覆写此抽象方法
enum Color{ RED("红色"){ public String getMessage(){ return this.toString(); } }, GREEN("绿色"){ public String getMessage(){ return this.toString(); } }, BLUE("蓝色"){ public String getMessage(){ return this.toString(); } } ; private String title ; private Color(String title){ this.title = title ; } @Override public String toString(){ return this.title ; } public abstract String getMessage() ; } class Demo{ public static void main(String[] args) { System.out.println(Color.RED.getMessage()); // 红色 } }
枚举类不建议写太多内容
115 枚举应用案例
enum Sex{ MAN("男"), FEMALE("女") ; private String title; private Sex(String title){ this.title = title ; } @Override public String toString(){ return this.title ; } } class Person{ private String name ; private int age ; private Sex sex ; public Person(String name, int age, Sex sex){ this.name = name ; this.age = age ; this.sex = sex ; } @Override public String toString(){ return "Person(" + this.name + " " + this.age + " " + this.sex + ")"; } } class Demo{ public static void main(String[] args) { Person person = new Person("张三", 23, Sex.MAN); System.out.println(person); // Person(张三 23 男) } }