返回顶部
扩大
缩小

Heaton

第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);
			}
		}
		
	}
	
	
	
}







posted on 2018-09-20 22:11  咘雷扎克  阅读(266)  评论(0编辑  收藏  举报

导航