第6章 面向对象(下)
6、面向对象(下) | |
6.1 关键字:static(类变量、类方法、单例(Singleton)设计模式) | 1课时 |
6.2 理解main方法的语法 | 1课时 |
类的成员之四:初始化块 | 1课时 |
6.4 关键字:final | 1课时 |
6.5 抽象类(abstract class)与抽象方法(模板方法设计模式(TemplateMethod)) | 1课时 |
6.6 更彻底的抽象:接口(interface)(工厂方法(FactoryMethod)和代理模式(Proxy)) | 1课时 |
6.7 类的成员之五:内部类 | 1课时 |
6-1 关键字:static
案例
/**
* static关键字的使用:
* 1.static:静态的
*
* 2.static可以用来修饰:属性、方法、代码块、内部类。
*
* 3. 使用static修饰属性:类变量(或静态变量)
* >使用static修饰的变量,被类的所有对象所共享:类的所有对象共同同一个静态变量。
* 对比:不用static修饰的属性,称为:实例变量。每个对象拥有一份实例变量。通过对象a修改某个实例变量,
* 不会影响其他对象同名的实例变量的值。
* >我们可以通过对象a去调用或修改静态变量的值,那么会影响其他对象对此静态变量的调用。
* >静态变量和实例变量在内存中分配的位置不同:
* 实例变量,随着对象的创建而产生,分配在堆空间中。
* 静态变量,随着类的加载而产生的,分配在方法区。
* >静态变量的加载要早于对象的创建。
* > 静态变量 非静态变量(实例变量)
* 类 可以 不可以
* 对象 可以 可以
*
* 4. 使用static修饰方法:静态方法
* >随着类的加载而加载
* > 静态方法 非静态方法
* 类 可以 不可以
* 对象 可以 可以
* >静态方法内:可以调用静态的属性或静态的方法。不可以调用非静态的属性和非静态的方法。
* 非静态的方法内:可以调用非静态的属性和非静态的方法。也可以调用静态的属性或静态的方法。
*
* 5. 如何判定属性是否需要声明为static的?是否需要类的多个对象来共享此属性;很多常量都声明为static的
*
* 如何判定方法是否需要声明为static的?操作静态变量的方法;工具类中的方法。(Math.random();)
*
*
*/
public class StaticTest {
public static void method(){
}
public static void main(String[] args) {
Chinese c1 = new Chinese();
c1.name = "孙杨";
c1.age = 20;
c1.nation = "CHN";
System.out.println(c1);
Chinese c2 = new Chinese();
c2.name = "姚明";
c2.age = 35;
//c2.nation = "CHN";
c2.nation = "中国";
System.out.println(c2);
System.out.println(c1);
System.out.println(Chinese.nation);
// System.out.println(Chinese.name);
System.out.println(Math.PI);
c1.show();
Chinese.show();
// System.out.println(Chinese.toString());
System.out.println();
// StaticTest t = new StaticTest();
// t.method();
// method();
}
}
class Chinese{
String name;
int age;
static String nation;
@Override
public String toString() {
return "Chinese [name=" + name + ", age=" + age + ", nation=" + nation + "]";
}
public static void show(){
System.out.println("我是一个中国人!");
Chinese.info();
System.out.println("nation = " + nation);
// this.display();
// System.out.println("name = " + name);
}
public static void info(){
System.out.println("合唱“中国人”");
}
//非static的方法
public void display(){
System.out.println("我叫" + name + ",今年" + age + "岁");
//静态结构:
info();
System.out.println("nation = " + nation);
}
}
public class ArrayUtilTest {
public static void main(String[] args) {
// ArrayUtil util = new ArrayUtil();
int[] arr1 = new int[]{23,5,23,64,66,-9,75,-77,3};
int max = ArrayUtil.getMax(arr1);
System.out.println("最大值为:" + max);
int avg = ArrayUtil.getAvg(arr1);
System.out.println("平均数为:" + avg);
int[] arr2 = ArrayUtil.copy(arr1);//arr2是对arr1的复制
ArrayUtil.reverse(arr1);
System.out.println("遍历arr1:");
ArrayUtil.print(arr1);
System.out.println("遍历arr2:");
ArrayUtil.print(arr2);
System.out.println("对arr1进行排序");
ArrayUtil.sort(arr1,"ascend");
ArrayUtil.print(arr1);
System.out.println("查找66在arr2数组中出现的位置");
int index = ArrayUtil.getIndex(arr2, 666);
if(index != -1){
System.out.println("找到了指定元素,在数组中的索引为:" + index);
}else{
System.out.println("在数组中未找到指定的元素");
}
}
}
案例
/**
* 操作数组的工具类
*
*/
public class ArrayUtil {
/**
* 求数组的最大值
* @author shkstart 邮箱:shkstart@126.com
* @param arr : 要获取数组最大值对应的数组
* @return 指定数组的最大值
*/
public static int getMax(int[] arr) {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
return max;
}
// 求数组的最小值
public static int getMin(int[] arr) {
int min = arr[0];// alt + shift + r
for (int i = 1; i < arr.length; i++) {
if (min > arr[i]) {
min = arr[i];
}
}
return min;
}
// 求数组的总和
public static int getSum(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
// 求数组的平均数
public static int getAvg(int[] arr) {
int avg;
avg = getSum(arr) / arr.length;
return avg;
}
// 数组的复制
public static int[] copy(int[] arr) {
int[] arr1 = new int[arr.length];
for (int i = 0; i < arr1.length; i++) {
arr1[i] = arr[i];
}
return arr1;
}
// 数组的反转
public static void reverse(int[] arr) {
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// 数组中指定元素的查找:线性查找
// 如果在数组中找到了此元素,则返回元素在数组中的索引。如果没找到,返回-1.
public static int getIndex(int[] arr, int value) {
for (int i = 0; i < arr.length; i++) {
if (value == arr[i]) {
return i;
}
}
return -1;
}
// 数组的排序:使用冒泡排序实现
public static void sort(int[] arr,String detail) {
if("ascend".equals(detail)){//if(detail.equals("ascend")){//升序:从小到大
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {// 比较相邻的两个元素的值所需要的索引
if (arr[j] > arr[j + 1]) {
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;
//正确的交换
swap(arr,j,j + 1);
//不正确的交换
// swap(arr[j],arr[j + 1]);
}
}
}
}else if("descend".equals(detail)){//}else if(detail.equals("descend")){//降序:从大到小
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {// 比较相邻的两个元素的值所需要的索引
if (arr[j] < arr[j + 1]) {
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;
//正确的交换
swap(arr,j,j + 1);
//不正确的交换
// swap(arr[j],arr[j + 1]);
}
}
}
}else{
System.out.println("输入的排序方式有误!");
}
}
//
private static void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void swap(int m,int n){
int temp = m;
m = n;
n = temp;
}
//遍历数组
public static void print(int[] arr){
for(int i = 0;i < arr.length;i++){
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
案例
/**
* static关键字的应用
*
*/
public class CircleTest {
public static void main(String[] args) {
Circle c1 = new Circle(12.3);
Circle c2 = new Circle(12.3);
System.out.println(c1);
System.out.println(c2);
System.out.println("创建的圆的个数为:" + Circle.getTotal());
}
}
class Circle{
private double radius;
private static int total;//记录创建的圆的个数
private int id;//圆的编号
private static int init = 1001;
public Circle(double radius){
this();
this.radius = radius;
// this.id = init++;
// total++;
}
public Circle(){
total++;
this.id = init++;
}
@Override
public String toString() {
return "Circle [radius=" + radius + ", id=" + id + "]";
}
public static int getTotal() {
return total;
}
}
练习
/*
* 编写一个类实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,
* 定义封装这些属性的方法。账号要自动生成。
编写主类,使用银行账户类,输入、输出3个储户的上述信息。
考虑:哪些属性可以设计成static属性。
*/
public class AccountTest {
public static void main(String[] args) {
Account acct1 = new Account("abc123", 20000);
System.out.println(acct1);
Account acct2 = new Account();
System.out.println(acct2);
}
}
class Account{
private int id;//账号
private String password = "qwerty";//密码
private double balance;//余额
private static double interestRate;//利率
private static double minBalance = 1.0;//最小余额
private static int init = 1001;//用于自动生成id
public Account(String password,double balance){
this.password = password;
this.balance = balance;
this.id = init++;
}
public Account(){
this.id = init++;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public static double getInterestRate() {
return interestRate;
}
public static void setInterestRate(double interestRate) {
Account.interestRate = interestRate;
}
public static double getMinBalance() {
return minBalance;
}
public static void setMinBalance(double minBalance) {
Account.minBalance = minBalance;
}
public int getId() {
return id;
}
@Override
public String toString() {
return "Account [id=" + id + ", password=" + password + ", balance=" + balance + "]";
}
}
饿汉式
/**
* 一、设计模式:
* 1.设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式
* 2.总结归纳出经典的23种设计模式。
*
* 二、单例设计模式(掌握)
* 1.解决的问题:保证在整个软件系统中,只提供当前类的一个实例
* 2.如何实现:①饿汉式(如下的4步) ②懒汉式
* 3.对比两种实现方式?
* 饿汉式:不存在线程安全问题。
* 懒汉式:延迟对象的创建,节省内存空间。存在线程安全问题的。
*
*
* 三、面试题:单例设计模式的实现。
*
*/
public class SingletonTest1 {
public static void main(String[] args) {
// Bank bank1 = new Bank();
// Bank bank2 = new Bank();
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2);
}
}
//饿汉式
class Bank{
//1.私有化构造器
private Bank(){}
//2.内部提供一个当前类的实例
//4.此实例也必须静态化
private static Bank bank = new Bank();
//3.提供公共的静态的方法,返回当前类的对象
public static Bank getInstance(){
return bank;
}
}
懒汉式
public class SingletoTest2 {
public static void main(String[] args) {
Bank1 bank1 = Bank1.getInstance();
Bank1 bank2 = Bank1.getInstance();
System.out.println(bank1 == bank2);
}
}
//懒汉式:
class Bank1{
//1.私有化构造器
private Bank1(){}
//2.声明当前类的实例
//4.此实例也必须静态化
private static Bank1 bank = null;
//3.提供公共的方法获取当前类的实例
public static Bank1 getInstance(){
if(bank == null){
synchronized(Bank1.class){
if(bank == null){
bank = new Bank1();}
}
}
return bank;
}
}
6-2 理解main方法的语法
案例
/**
* 类中main()的使用说明:
* 1.main()是程序的入口,格式是固定的:public static void main(String[] args){}
* 2.main()是一个静态方法,可以通过类,进行调用。
* 3.main():作为我们与控制台交互的方式。
*
*/
public class MainTest {
//程序的入口
public static void main(String[] args) {
Main.main(new String[100]);
}
}
class Main {
//静态方法
public static void main(String[] args) {
for(int i = 0;i < args.length;i++){
args[i] = "args_" + i;
System.out.println(args[i]);
}
}
}
public class MainDemo { public static void main(String[] args) {
for(int i = 0;i < args.length;i++){
System.out.println(args[i] + "!!!");
//转换
int num = Integer.parseInt(args[i]);
System.out.println(num);
}
}
}
6-3 类的成员之四:初始化块
案例
/**
* 类的成员之四:代码块(或初始化块)
*
* 1.代码块的作用:用来初始化类、对象的信息。
*
* 2.代码块的分类:静态代码块 vs 非静态代码块
*
* 3.静态代码块:
* >可以提供输出语句
* >随着类的加载而执行,且只被加载一次
* >作用:初始化类的加载信息。
* >内部只能调用当前类中静态的属性、方法。不能调用非静态的属性、方法
* >如果定义了多个静态代码块,按照定义的先后顺序执行。
* >静态代码块的执行要早于非静态代码块
*
* 非静态代码块:
* >可以提供输出语句
* >随着对象的创建而执行
* >每创建一个对象,都会执行一次
* >作用:用来初始化对象的属性信息
* >内部可以调用静态的属性、方法,也可以调用非静态的属性、方法
* >如果定义了多个非静态代码块,按照定义的先后顺序执行。
*
*
* 4.总结:给属性赋值的位置的先后顺序:
* ①默认初始化
* ②显式初始化 / 在代码块中初始化
* ③构造器中初始化
* ④有了对象以后,通过"对象.属性"或"对象.方法"的方式,赋值
*
*
*/
public class BlockTest {
public static void main(String[] args) {
Person p1 = new Person();
// p1.eat();
// System.out.println(p1.name);
System.out.println();
Person p2 = new Person();
System.out.println(p2.age);
Person p3 = new Person(3);
System.out.println(p3.age);
}
}
class Person{
String name;
int age = 2;
static String desc;//人的描述
public Person(){}
public Person(int age){
this.age = age;
}
public void eat(){
System.out.println("吃饭");
}
//静态代码块
static {
System.out.println("静态代码块2");
}
static{
System.out.println("静态代码块1");
desc = "我是地球人!";
info();
//不能调用非静态结构
// eat();
// name = "Tom";
}
//非静态代码块
{
System.out.println("非静态代码块2");
}
{
System.out.println("非静态代码块1");
age = 1;
eat();
//调用静态的结构
info();
System.out.println(desc);
}
public static void info(){
System.out.println("我是静态方法!");
}
}
案例
//总结:由父及子,静态先行!
class Root{
static{
System.out.println("Root的静态初始化块");
}
{
System.out.println("Root的普通初始化块");
}
public Root(){
System.out.println("Root的无参数的构造器");
}
}
class Mid extends Root{
static{
System.out.println("Mid的静态初始化块");
}
{
System.out.println("Mid的普通初始化块");
}
public Mid(){
super();
System.out.println("Mid的无参数的构造器");
}
public Mid(String msg){
//通过this调用同一类中重载的构造器
this();
System.out.println("Mid的带参数构造器,其参数值:"
+ msg);
}
}
class Leaf extends Mid{
static{
System.out.println("Leaf的静态初始化块");
}
{
System.out.println("Leaf的普通初始化块");
}
public Leaf(){
//通过super调用父类中有一个字符串参数的构造器
super("张三");
System.out.println("Leaf的构造器");
}
}
public class TestLeaf{
public static void main(String[] args){
new Leaf();
System.out.println();
new Leaf();
}
}
6-4 关键字:final
案例
/**
* final关键字的使用:
*
* 1.final:最终的
*
* 2.final可以用来修饰:变量、方法、类
*
* 3.final修饰类:此类不可以被继承。比如:String / StringBuffer类
*
* 4. final修饰方法:此方法不能被重写。比如:Object类的getClass()
*
* 5.final修饰变量:表明此变量就是一个常量。比如:Math类中的PI
* 5.1使用final修饰属性,可以考虑的赋值的位置有:①显式初始化 ②代码块中初始化 ③构造器中
* 5.2使用final修饰形参:在方法调用时,传递实参,给常量赋值。一旦赋值,方法内不可修改此常量的值。
*
* static final所修饰的属性:全局常量。
*
*/
public class FinalTest {
final int MY_INT = 10;
final double PI;
final int NUM;
// final int N;
public FinalTest(int num){
this.NUM = num;
}
public FinalTest(){
// this(10);
this.NUM = 10;
}
{
PI = 3.14;
}
public void method(){
// MY_INT = 20;
// N = 10;
}
public static void method(final int num){
// num++;
// final int NUM = 10;
System.out.println(num);
}
public static void main(String[] args) {
method(10);
}
}
final class AA {
}
// class BB extends AA{
//
// }
class CC {
public final void method() {
}
}
class DD extends CC {
// public void method() {
//
// }
}
答案:
一题,不能修改final修饰的变量 可以return x+1;
二题,没问题
6-5 抽象类与抽象方法
案例
/**
*
* abstract关键字的使用
* 1.abstract:抽象的
* 2.可用修饰的结构:类 、 方法
*
* 3.abstract修饰类:抽象类
* >不可实例化
* >仍然存在构造器。构造器的作用:便于子类对象实例化时进行调用
* >通常情况,我们会提供抽象类的子类,让子类实例化,调用父类的结构。
* >抽象类中不一定有抽象方法;抽象方法所在的类,一定是抽象类。
*
* 4.abstract修饰方法:抽象方法(没有方法体)
* >如果子类重写了父类中的所有的抽象方法,则此子类可以实例化
* >如果子类没有重写父类中的所有的抽象方法,则子类仍为抽象类
*
*
* 5.前提:抽象性使用的前提是类的继承性。
*
*/
public class AbstractTest {
public static void main(String[] args) {
// Person p1 = new Person();
// p1.eat();
}
}
abstract class Creature{
public abstract void breath();
}
abstract class Person extends Creature{
String name;
int age;
public Person(){}
public Person(String name,int age){
this.name = name;
this.age = age;
}
//不是抽象方法
// public abstract void eat(){
//
// }
//抽象方法
public abstract void eat();
public abstract void walk();
}
class Student extends Person{
public void eat(){
System.out.println("学生多吃有营养的食物");
}
@Override
public void walk() {
System.out.println("学生背着书包走路!");
}
public void breath(){
System.out.println("学生多呼吸没有雾霾的空气");
}
}
abstract class Worker extends Person{
public void eat(){
System.out.println("工人多吃肉!");
}
}
案例
/**
* abstract关键字不能用来修饰:属性、构造器。
*
* abstract关键字不能与 final , private , static 共用。
*/
public abstract class AbstractTest1 {
// private abstract void method();
// public abstract final void method();
// public abstract static void method();
}
练习
/*
* 编写一个Employee类,声明为抽象类,包含如下三个属性:name,id,salary。
* 提供必要的构造器和抽象方法:work()。
*/
public abstract class Employee {
private String name;
private int id;
private double salary;
public Employee() {
super();
}
public Employee(String name, int id, double salary) {
super();
this.name = name;
this.id = id;
this.salary = salary;
}
public abstract void work();
}
public class CommonEmployee extends Employee {
public CommonEmployee(String name, int id, double salary) {
super(name, id, salary);
}
@Override
public void work() {
System.out.println("员工就好好上班,不要搞情绪!");
}
}
public class Manager extends Employee { private double bonus;
public Manager(String name, int id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("不给奖金,不管理");
}
}
/* * 请使用继承的思想,设计CommonEmployee类和Manager类,要求类中提供必要的方法进行属性访问。 * */ public class EmployeeTest { public static void main(String[] args) {
Manager manager = new Manager("郭台铭", 1001, 1000, 10000);
manager.work();
CommonEmployee employee = new CommonEmployee("小明", 100001, 5000);
employee.work();
}
}
模板方法的设计模式
/**
* 模板方法的设计模式:抽象的应用
*/
public class TemplateTest {
public static void main(String[] args) {
SubTemplate sub = new SubTemplate();
sub.costTime();
}
}
abstract class Template {
// 不确定的部分
public abstract void code();
// 确定的部分:执行某段代码需要花费的时间
public void costTime() {
long start = System.currentTimeMillis();
this.code();
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));
}
}
class SubTemplate extends Template {
// 计算1000以内质数的输出
@Override
public void code() {
boolean isFlag = true;
for (int i = 2; i <= 1000; i++) {
for (int j = 2; j <= Math.sqrt(i); j++) {
if (i % j == 0) {
isFlag = false;
break;
}
}
if (isFlag) {
System.out.println(i);
}
isFlag = true;
}
}
}
6-6 接口(interface)
接口的使用
/**
* 接口的使用:
* 1.接口(interface) 是与类(class)并列的结构
*
* 2.如何定义一个接口.使用interface关键字
* 3.接口中只能定义常量和抽象方法 ----> JDK7.0及以前。 (JDK8.0接口中引入默认方法、静态方法)
* 常量的定义:public static final修饰。
* 抽象方法的定义:public abstract修饰
*
* 4.接口中不能声明构造器! 接口是不可以直接实例化的。
*
* 5.类与接口之间的关系:实现(implements)关系. 类实现接口以后,就获取了接口中声明的结构:常量、抽象方法
* 格式:class SubClass extends SuperClass implements InterfaceA
*
* 6.类实现接口以后,要么实现接口中的所有抽象方法,方可实例化。
* 要么当前类声明为抽象类(因为内部包含从接口中获取的抽象方法)
*
* 7.java规定:类可以实现多个接口。--->一定程度上,解决了java类的单继承的局限性。
*
* 8.java规定:接口与接口之间是继承关系。而且是可以多继承的!
*
*/
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(CompareA.E);
// CompareA.E = 2.7;
}
}
interface CompareA{
//常量
public static final double PI = 3.14;
//省略了public static final的声明
double E = 2.71828;
public abstract void method1();
//省略了public abstract的声明
void method2();
// public CompareA(){
//
// }
}
interface CompareB{
public void method3();
}
class ComClass extends Object implements CompareA,CompareB{
@Override
public void method1() {
// TODO Auto-generated method stub
}
@Override
public void method2() {
// TODO Auto-generated method stub
}
@Override
public void method3() {
// TODO Auto-generated method stub
}
}
abstract class ComClass1 extends Object implements CompareA{
}
//接口的多继承性
interface CompareC extends CompareA,CompareB{
}
/**
* 接口的使用:
* 1.接口与具体的实现类之间存在多态性
* 2.如何提供接口的匿名实现类,如何去创建匿名对象
* 3.接口,实际上可以理解定义了一套相应功能的规范、标准。
*/
public class USBTest {
public static void main(String[] args) {
Computer com = new Computer();
//1.创建接口的实现类的对象
Printer printer = new Printer();
com.transferDate(printer);//多态性的体现:USB usb = new Printer();
//2.创建接口的实现类的匿名对象
com.transferDate(new Flash());
//3.创建接口的匿名实现类的对象
USB usb = new USB(){
@Override
public void start() {
System.out.println("手机开始工作...");
}
@Override
public void stop() {
System.out.println("手机停止工作...");
}
};
com.transferDate(usb);
//4.创建接口的匿名实现类的匿名对象
com.transferDate(new USB(){
@Override
public void start() {
System.out.println("mp3开始工作...");
}
@Override
public void stop() {
System.out.println("mp3停止工作...");
}
});
}
}
class Computer{
public void transferDate(USB usb){
usb.start();
System.out.println("具体的操作过程");
usb.stop();
}
}
interface USB{
//常量:声明USB接口的长、宽、最高数据传输速度等
//抽象方法
public void start();
public void stop();
}
class Flash implements USB{
@Override
public void start() {
System.out.println("U盘开始工作....");
}
@Override
public void stop() {
System.out.println("U盘结束工作....");
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("打印机开始工作....");
}
@Override
public void stop() {
System.out.println("打印机停止工作....");
}
}
工厂方法的设计模式
/**
* @author Heaton
* @email tzy70416450@163.com
* @date 2018/9/27 0027 10:49
* @describe 工厂方法,接口应用
* //接口的应用:工厂方法的设计模式
* //体会:面向接口编程的思想
*/
public class FactoryMethodTest {
//正式版
public static IworkFactory method(String str){
if("老师".equals(str)|| str.toUpperCase().equals("TEACHER")){
return new TeacherWorkFactory();
}else if("学生".equals(str)||str.toLowerCase().equals("student")){
return new StudentWorkFactory();
}
return null;
}
public static void main(String[] args) {
// 测试版
// IworkFactory factory1 = new StudentWorkFactory();
// Work work1 = factory1.getWork();
// work1.doWork();
//
// IworkFactory factory2 = new TeacherWorkFactory();
// Work work2 = factory2.getWork();
// work2.doWork();
Scanner s = new Scanner(System.in);
System.out.println("请输入谁做作业!老师 or 学生");
// FactoryMethodTest.method(s.next()).getWork();
IworkFactory factory = FactoryMethodTest.method(s.next());
Work work = factory.getWork();
work.doWork();
}
}
interface IworkFactory {
public abstract Work getWork();
}
class StudentWorkFactory implements IworkFactory{
@Override
public Work getWork() {
return new StudentWork();
}
}
class TeacherWorkFactory implements IworkFactory{
@Override
public Work getWork() {
return new TeacherWork();
}
}
interface Work {
void doWork();
}
class StudentWork implements Work{
@Override
public void doWork() {
System.out.println("学生学习,写作业@");
}
}
class TeacherWork implements Work{
@Override
public void doWork() {
System.out.println("老师讲课,检查作业@");
}
}
代理模式
//接口的应用:代理模式---静态代理。
public class ProxyTest {
public static void main(String[] args) {
NetWork work = new RealServer();
ProxyServer proxy = new ProxyServer(work);
proxy.browse();
}
}
interface NetWork{
public void browse();
}
//被代理类
class RealServer implements NetWork{
@Override
public void browse() {
System.out.println("真实服务器联网浏览网页");
}
}
//代理类
class ProxyServer implements NetWork{
private NetWork work;
public ProxyServer(NetWork work){
this.work = work;
}
public void check(){
System.out.println("检查网络连接是否通畅");
}
@Override
public void browse() {
check();
System.out.println("代理服务器代理真实服务器操作:");
work.browse();
}
}
/** * @author Heaton * @email tzy70416450@163.com * @date 2018/9/27 0027 16:56 * @describe 房屋代理 */ public class houseTest { public static void main(String[] args) { Intermediary i = new Intermediary(new Homeowner()); i.sellingAHouse();
System.out.println("*****");
Intermediary ii = new Intermediary(new Shopowner());
ii.sellingAHouse();
}
}
interface House{
void sellingAHouse();
}
//被代理,房主
class Homeowner implements House{
@Override
public void sellingAHouse(){
System.out.println("我要卖房子");
}
}
//被代理老板
class Shopowner implements House{
@Override
public void sellingAHouse(){
System.out.println("我要卖商铺");
}
}
//代理
class Intermediary{
private House h;
public Intermediary(House h) {
this.h = h;
}
private void sameCity58(){
System.out.println("58同城,注册房屋");
}
public void sellingAHouse(){
h.sellingAHouse();
System.out.println("我是房产中介,开始帮您卖房子");
sameCity58();
}
}
补充
/**
* java8中规范:
* 接口中可以定义静态方法、默认方法
*
*/
public interface CompareA {
//静态方法
public static void method1(){
System.out.println("CompareA:北京");
}
//默认方法
default void method2(){
System.out.println("CompareA:上海");
}
public default void method3(){
System.out.println("CompareA:深圳");
}
}
public interface CompareB { default void method2(){ System.out.println("CompareB:上海"); } }
public class SubClass extends SuperClass implements CompareA,CompareB{
public static void main(String[] args) {
SubClass s = new SubClass();
s.method();
System.out.println();
s.myMethod();
}
public void method(){
//编译不通过
// this.method1();
// SubClass.method1();
//知识点1:接口中定义的静态方法,只能通过接口进行调用。
CompareA.method1();
//知识点2:通过实现类的对象,调用接口中的默认方法。
//知识点3:如果类实现的接口和继承的父类中,定义了同名同参数的方法,那么子类在没有重写此方法的情况下,
//默认调用的是父类中声明的方法。---“类优先”原则
this.method2();
this.method3();
}
//知识点4:如果实现类实现了多个接口,接口中定义了同名同参数的方法。那么此时对于实现类来讲,会出现接口冲突问题。
//解决方法:要求实现类必须重写接口中的方法。
public void method2(){
System.out.println("SubClass:北京");
}
public void myMethod(){
method2();//调用当前类重写的方法
super.method2();//调用父类中被重写的方法
//知识点5:如何在实现类的方法中调用接口中的默认方法
CompareA.super.method2();
CompareB.super.method2();
}
}
public class SuperClass {
public void method2(){
System.out.println("SuperClass:北京");
}
}
答案:x不明确,编译出错
答案:接口属性默认final的,ball不能再赋值
练习
public interface CompareObject {
//若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
public int compareTo(Object o);
}
public class Circle {
// private double radius;
private Double radius;
public Double getRadius() {
return radius;
}
public void setRadius(Double radius) {
this.radius = radius;
}
public Circle() {
super();
}
public Circle(Double radius) {
super();
this.radius = radius;
}
}
public class ComparableCircle extends Circle implements CompareObject{
public ComparableCircle(Double radius) {
super(radius);
}
@Override
public int compareTo(Object o) {
if(o instanceof ComparableCircle){
ComparableCircle c = (ComparableCircle)o;
//不合适
// return (int)(this.getRadius() - c.getRadius());
//方式一:
// if(this.getRadius() > c.getRadius()){
// return 1;
// }else if(this.getRadius() < c.getRadius()){
// return -1;
// }else{
// return 0;
// }
//方式二:
// return this.getRadius().compareTo(c.getRadius());
//方式三:
return Double.compare(this.getRadius(), c.getRadius());
}
// return 0;
throw new RuntimeException("传入的类型非法!");
}
}
public class InterfaceTest { public static void main(String[] args) { ComparableCircle c1 = new ComparableCircle(2.3); ComparableCircle c2 = new ComparableCircle(2.2); System.out.println(c1.compareTo(c2)); } }
6-7 类的成员之五:内部类
案例
/**
* 类的成员之五:内部类(InnerClass)
* 1.定义:java语言在一个类A的内部再定义另外一个类B。
* 将类B:称作内部类 ; 类A:外部类
*
* 2.内部类,作为一个类:
* >内部可以定义属性、方法、构造器等
* >可以被final修饰
* >可以被abstract修饰
*
* 作为外部类的一个成员:
* >可以被4种不同的权限修饰
* >可以被static修饰
* >可以调用外部类的结构:属性、方法等
*
*
* 3.内部类的分类:成员内部类(静态的;非静态的) vs 局部内部类
*
* 4.需要掌握的知识点:
* 4.1 如何创建成员内部类的对象?
* 4.2 如何调用外部类的结构?
* 4.3 关于局部内部类在开发中的体现。见InnerClassTest1.java
*
*/
public class InnerClassTest {
public static void main(String[] args) {
//创建静态的成员内部类对象
Person.Dog dog = new Person.Dog();
dog.show();
//创建非静态的成员内部类对象
// Person.Bird bird = new Person.Bird();
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.info();
bird.display("黄鹂");
}
}
class Person{
String name = "小明";
int age = 1;
//静态的成员内部类
public static class Dog{
public void show(){
System.out.println("卡拉是条狗");
}
}
//非静态的成员内部类
public class Bird{
String name = "麻雀";
public void info(){
System.out.println("我是一只小小鸟");
}
public void display(String name){
Person.this.eat();//eat();
// System.out.println(age);
System.out.println(name);//形参
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
}
}
public void method(){
//局部内部类
class A{
}
}
public void eat(){
System.out.println("人吃饭!");
}
}
/** * 局部内部类在开发中的体现 */ public class InnerClassTest1 {
//在开发中少见
public void method(){
class A{
}
}
//此方法的返回值声明为接口、抽象类。那么我们需要在方法内部提供接口的实现类或抽象类的子类。
public Comparable getComparable(){
//方式一:
// //局部内部类:声明一个实现Comparable接口的类
// class MyComparable implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// // TODO Auto-generated method stub
// return 0;
// }
//
// }
//
// return new MyComparable();
//方式二:返回了实现接口的匿名类的匿名对象
return new Comparable(){
@Override
public int compareTo(Object o) {
return 0;
}
};
}
//如下的情况在anroid中常见:
public void onCreate(){
//提供button的监听器(接口的形式存在)的实现类
// button.setOnClickListener(new OnClickListener(){
//
// public void onClick(){
//
//
// }
//
// });
}
//局部内部类的方法中调用局部内部类所在的方法中定义的局部变量,要求此局部变量声明为final的。
//在java7及以前的版本中:需要显式的声明为final。
//java8中可以省略final的声明。
public void myMethod(){
int num = 10;//方法内的局部变量
//局部内部类
class A{
//局部内部类中的方法
public void method1(){
// num = 11;
System.out.println(num);
}
}
}
}
您的资助是我最大的动力!
金额随意,欢迎来赏!