zoukankan      html  css  js  c++  java
  • 第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);
    			}
    		}
    		
    	}
    	
    	
    	
    }
    







  • 相关阅读:
    Linux 定时任务
    VIM快速使用
    ulimit 命令
    PG语句
    linux下的PGSQL安装步骤
    linux下安装mysql 5.5和5.6.32
    linux下安装达梦数据库(DM8)x86版本
    redis配置
    sql server 2008安装
    linux下安装部署oracle
  • 原文地址:https://www.cnblogs.com/ttzzyy/p/9683658.html
Copyright © 2011-2022 走看看