首页 > 编程语言 > 详细

Java面向对象(下)

时间:2021-05-13 10:03:12      阅读:23      评论:0      收藏:0      [点我收藏+]

面向对象(下)

技术分享图片

static关键字

    1. static可以用来修饰的结构:主要用来修饰类的内部结构
    • 属性、方法、代码块、内部类
    1. static修饰属性:静态变量(类变量)
    /* 2. 使用static修饰属性,静态变量
     * 	 2.1 属性:
     * 		实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改一个对象的非静态属性时,不会导致其对象中的相同属性的修改
     *		静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量
     *	 2.2 static修饰属性的其他说明
     *			(1)静态变量随着类的加载而加载(实例变量随着类的创建而创建)
     *			(2)静态变量早于对象的创建
     *			(3)由于类只会加载一次,所以静态变量在内存怒中也只会存在一份,存在于方法区的静态域中
     *			(4) 类变量    实例变量
     *			类	  yes	   no		
     *			对象   yes	  yes
     *	static举例:System.out.println()的out ; Math.PI
     *		System.class下
     *		public static final PrintStream out = null;
     *		PrintStream.class下
     *		public void println() {newLine();}
     * /
    
    1. 静态变量内存解析
      技术分享图片
    1. static修饰方法:静态方法、类方法
/* 4. 使用static修饰方法
 * 		① 随着类的加载而加载,可以通过“类.静态方法”的使用进行调用
 * 		②		静态方法	非静态方法
 * 		类		yes		no
 * 		对象		yes		yes
 * 		③ 静态方法中,只能调用静态的方法或者属性
 * 		 非静态方法中,可以调用非静态的方法或属性,也可以调用静态的方法或者属性
*/	
    1. static的注意点
 * 5. static注意点
 * 	在静态的方法中, 不能使用this关键字,super关键字	(对象的父类,对象都没有,怎么用?)
    1. 如何判定属性和方法应该使用static关键字?
/* 6.1 开发中如何确定一个属性是否要声明为static?
 * 	   *  属性可以被多个对象所共享,不会随着对象的不同而不同
 * 	   *  类中的常量,也常常声明为static
 */
/* 6.2 开发中如何确定一个方法是否要声明为static?
 	  *	 操作静态属性的方法,通常设置为static的。(方法权限和属性权限一般一致)
 	  *	 工具类中的方法,习惯上声明为static的。好处:不必再找对象
 	  	 比如Math, Arrays, Collections
 	  	 工具类中的方法一般都有形参,主要体会在做的事情,而不在于谁做的,工具类是帮我们做事情的
*/
//   8. 自动生城的toString()只会输出私有的 static不会输出
    1. 使用举例:
    • Arrays ;Math ; Collection等工具类
    • ② 单例模式

static应用:单例(Singleton)设计模式

  • 总共23种

  • 总体来说设计模式分为三大类:

    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

    结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

  • 设计模式是大量的实践中总结和理论化之后优选的代码结构,编程风格,以及解决问题的思考方式。设计模式免去我们在思考和摸索。

  • 所谓类的单例设计模式,就是采取一定的方法保证整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。如果我们要让类再一个虚拟中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为private,这样,就不能用new操作符在类的外部产生类的对象了,但在类的内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的

  • 单例模式优点:由于单例模式只生成一个实例,减少了系统性能开销,当一个对象产生需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在英勇启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

  • 实现方式

    • 饿汉式

    • package com.shc.java2;
      /*
       * 单例设计模式
       * 1. 所谓类的单例设计模式,就是采取一定的方法报这个在整个软件系统中,对某个类只能存在一个对象实例
       * 
       * 2. 如何实现?
       * 		懒汉式 vs 饿汉式
       * 懒汉式:用的时候才造
       * 饿汉式:加载的时候就造了
       * 
       * 3. 区分饿汉式和懒汉式
       * 		饿汉式: 
       * 			坏处:对象加载时间过长(对象一上来就有了)
       * 			好处:饿汉式是线程安全的
       * 		懒汉式: 
       * 			好处:延迟对象的创建
       * 			目前写法坏处:线程不安全 -->到多线程内容时,再修改
       */
      public class SingletonTest1 {
      	public static void main(String[] args) {
      //		Bank bank1 = new Bank(); error private构造器
      		
      		Bank b1 = Bank.getInstance();
      		Bank b2 = Bank.getInstance();
      		System.out.println(b1.equals(b2));//true 地址相同 二者管理的是同一个对象
      	}
      }
      
      class Bank{
      	//1.私有化类的构造器(避免在类的外部使用构造器产生对象)
      	private Bank() {
      		
      	}
      	
      	//2. 内部创建类的对象
      	private static Bank instance = new Bank();
      	
      	//3. 提供公共方法,返回类的对象
      	//设置为static 为了让外部在没有该类的对象的情况下就可以调用该类中的方法来获得对象
      	public static Bank getInstance() {
      		return instance;
      	}
      }
      
    • 懒汉式

    • package com.shc.java2;
      
      /*
       * 懒汉式 :不用就不造 需要用了才造
       */
      public class SingletonTest {
      	public static void main(String[] args) {
      		Order order1 = Order.getInstance();
      		Order order2 = Order.getInstance();
      		System.out.println(order1.equals(order2));//true
      	}
      }
      
      class Order{
      	
      	//1.私有化构造器
      	private Order(){
      		super();
      	}
      	
      	//2.声明当前类对象,没有初始化
      	private static Order instance = null;//此对象也必须声明为static的
      	
      	//3.声明public,static的返回当前类对象的方法
      	public static Order getInstance() {
      		if(instance==null) instance = new Order(); //防止重复产生对象
      		return instance;
      	}
      }
      
      
  • java.lang.Runtime (饿汉式)

    public class Runtime {
        private static final Runtime currentRuntime = new Runtime();
    
        private static Version version;
    
        /**
         * Returns the runtime object associated with the current Java application.
         * Most of the methods of class {@code Runtime} are instance
         * methods and must be invoked with respect to the current runtime object.
         *
         * @return  the {@code Runtime} object associated with the current
         *          Java application.
         */
        public static Runtime getRuntime() {
            return currentRuntime;
        }
    
        /** Don‘t let anyone else instantiate this class */
        private Runtime() {}
  • 应用场景

    • 网站的计数器,一般也是单例模式实现,否则难以同步。

    • 应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志 文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。

    • 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库 资源。

    • 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置 文件数据,都生成一个对象去读取。 ?

    • Application 也是单例的典型应用

      ? - 应用程序运行起来就有一个进程,在应用程序执行的进行中,只会存在一个Appliaction

    • Windows的Task Manager (任务管理器)就是很典型的单例模式

    • Windows的Recycle Bin (回收站)也是典型的单例应用。在整个系统运行过程 中,回收站一直维护着仅有的一个实例

main()方法说明

/*
 * main()方法的使用说明:
 * 1. main()方法作为程序的入口
 * 2. main()也可是一个普通的静态方法
 * 3. main()方法也可以作为与控制台交互的一种方式(之前,使用Scanner)
 * 4. eclipse交互:run as --> Run configuration -->目标字节码文件 -->Argument. 再填入字符串数组,以空格为分隔,有无""均可
 * 5. 命令行交互: cmd--> javac MainDemo.java -->java MainDemo 这是不传参数 ---> java MainDemo "55" 99 .. 这是传参数
 */
命令行如何将控制台获取的数据传给形参:String args[]
    运行时:java 类名"Tom""Jerry""123""true"
    syso(args[0]); //Tom
	syso(args[3]); //true
	syso(args[4]); //Exception
  • 例子
package com.shc.java2;
public class MainTest {
	//main()中不可以直接调本类的非static方法和属性,需要new对象再通过对象调用
	//因为main()方法是static的
	//public:方法权限 
	//调main()方法必须得有当前类来调,因为还没有产生对象,产生独对象得在main()里.所以是main()是static的
	public static void main(String[] args) {//入口
		Main.main(new String[10]);
//		show();
		hh();
	}
	
	public void show() {}
	public static void hh() {}
}

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]);
		}
	}
}
args_0
args_1
args_2
args_3
args_4
args_5
args_6
args_7
args_8
args_9
  • 小结·
public static void main(String[] args){//方法体}
/*权限修饰符*/
private 缺省 protected public -->封装性
/*修饰符*/
static \ final \ abstract \ native 可以用来修饰方法
/*方法名*/
//方法名:需要满足标识符命名规则,规范
/*形参列表*/
//重载vs重写 ; 参数的值传递机制 ; 对象多态性

代码块

  • 静态代码块与非静态代码块
package com.shc.java3;
/*
 * 类的成员之四:代码块(或初始化块)
 * 1. 代码块的作用:用来初始化类,对象
 * 2. 代码块如果有修饰的话,只能使用static
 * 3. 分类:静态代码块 vs 非静态代码块
 * 
 * 4. 静态代码块
 * 		内部可以有输出语句
 * 		随着类的加载而执行,而且只执行一次
 * 		作用:初始化类的信息
 * 		如果一个类中定义了多个静态代码块,则按照声明的先手顺序执行
 * 		静态代码块的执行优先于非静态代码块的执行
 * 		静态代码块内只能调用静态的属性,静态方法,不能调用非静态的结构
 * 		
 * 5. 非静态代码块
 * 		内部可以有输出语句
 * 		随着对象的创建而执行,每个对象创建都会执行一次
 * 		作用:可以在创建对象时,对对象的属性进行初始化
 * 		如果一个类中定义了多个非静态代码块,则按照声明的先手顺序执行
 * 		静态代码块内既能调用静态的属性,静态方法,也能调用非静态的结构
 * 
 * 对属性可以赋值的位置
 * ①默认初始化
 * ②显式初始化 / * ④在代码块中赋值 代码块先于构造器执行 显式初始化与代码块谁写在前面先执行谁
 * ③构造器中初始化
 * ⑤getter() setter()
 * 
 * 6. 静态代码块的使用情景
 * 
 */
public class BlockTest {
	public static void main(String[] args) {
//啥语句都没有时不会再加载person类
		String desc = Person.desc; //只有这句时输出    static block-1 static block-2
		Person p = new  Person(); //static block-1, static block-2, not static block-1, not static block-2
		Person p1 = new Person(); //static block-1, static block-2, not static block-1, not static block-2,  not static block-1, not static block-2 
//		System.out.println(p.age);
		///person.hh();
	}
}


class Person{
	String name;
	int age;
	static String desc = "我是一个人";
	public Person() {}
	//构造器
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	//static代码块
	//随着类的加载而执行
	static{
		System.out.println("static block-1");
		desc = "我爱学习";
	}
	static{
		System.out.println("static block-2");
		desc = "我爱学习";
	}
	
	//非static代码块
	//随着对象的创建而执行
	{
		System.out.println("not static block-1");
		age = 1;
	}
	
	{
		System.out.println("not static block-2");
		age = 1;
	}
	
	//方法
	public void eat() {
		System.out.println("吃饭");
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	//static方法随着类的加载而加载 但是没有执行
	public static void hh() {
		System.out.println("hh");
	}
}

final

    1. 修饰类、方法、变量
    1. 具体的:
package com.shc.java4;

import java.lang.constant.Constable;
import java.lang.constant.ConstantDesc;

//import jdk.internal.HotSpotIntrinsicCandidate;

/*
 * final:最终的
 * 1. final 可以用来修饰结构,类,方法,变量
 * 2. final 用来修是一个类:此类不能被其它类继承
 * 		比如:String类,System类,StringBuffer类
 * 		为什么String是final? 因为该有的方法都写好了,基本上以后不会在继承这个类去扩充了
 * 		public final class String  implements java.io.Serializable, Comparable<String>, CharSequence,
               Constable, ConstantDesc {
               
 * 3. final 用来修饰方法:该方法不可以被重写
 * 		比如: Object类中的getClass()
 * 		@HotSpotIntrinsicCandidate
		    public final native Class<?> getClass();
			    native:本地的
			    为什么这个方法没有写具体的方法体?
			    因为标名为natvie 代表接下来要调用底层的C/C++代码 这部分不对外开放
 
 * 4. final 修饰变量,此时的变量称为常量
 * 		4.1 final修饰属性,可以考虑赋值的位置有:
 * 				显式初始化 final int LEFT=10;
 * 				代码块中赋值
 * 				构造器中初始化 
 * 
 * 			如何选择?
 * 			如果造多个对象,这些对象的常量属性还一样.比如都设成0 那么就可以直接显示初始化.
 * 			如果要赋的不简单的一个值,需要调方法,方法还抛异常,那就只能在代码块中做
 * 			如果每个对象的常量的值不一样,那么就在构造器中进行
 * 		4.2 final修饰局部变量
 * 				尤其是使用final修饰形参时,表明此形参是一个常量,当我们调用此方法时,给常量形参赋一个实参,一旦传入以后,就只能在方法体内使用此形参,但不能进行重新赋值
 *
 *	static final  用来修饰属性: 即为全局常量
 *	(一起修饰方法较少,主要是修饰属性)
 *
 *Wrong!! final 参数只能使用不能修改
 *  public class Something {
		public int addOne(final int x) {
		return ++x;
		// return x + 1;
		}
	}
	
	Yes! 引用变量o不再管理其他对象即可
 *	public class Something {
	public static void main(String[] args) {
	Other o = new Other();
	new Something().addOne(o);
	}
	public void addOne(final Other o) {
	// o = new Other();
	o.i++;
	}
	}
	class Other {
	public int i;
	}
 *	
 */
public class FinalTest {
	//1. 显式初始化
	final int LEFT = 0;
	final int RIGHT ;
	final int DOWN;
//	final int UP;
	
	//2. 代码块中赋值
	{
		RIGHT = 1;
	}
	
	//3.构造器中初始化
	public FinalTest() {
		DOWN = 0;
	}
	
	//如果一个常量没有显式初始化也没有在代码块中初始化,那么就必须在构造器中初始化赋值
	public FinalTest(int n) {
		DOWN = n;
	}
	
	//
	public void show(final int num) {
//		num+=10;编译error
	}
//	public void setUP(int up) {
//		this.UP = up;
//	}
//	
}

final class FinalA{
	
}

//class A{
//	public final void show() {}
//}
//
//class B extends A{
//	public void show() {}
//}
//Multiple markers at this line
//- Cannot override the final method 
// from A
//- overrides com.shc.java4.A.show

//class B extends FinalA{
//	
//}

//class C extends String{
//	
//}

每天一考

    1. static修饰的属性,相较于实例变量,有哪些特别之处。
    • 随着类的加载而加载
    • 早于对象创建
    • 可以通过"对象.static属性"的方式进行调用
    1. final可以用来修饰哪些结构,分别表示什么意思
    • 类的内部结构:属性、方法、内部类、代码块。
    1. 代码实现单例模式的饿汉式
class Bank{
    //1.私有化类的构造器(避免在类的外部使用构造器产生对象)
    private Bank(){
	}
    
    //2.内部创建类的对象
    private static Bank instance = new Bank();
    
    //3.提供公共方法,返回类的对象
    //设置为static 为了让外部再没有该类的对象的情况下就可以调用该类中的方法来获得对象
    public static Bank getInstance(){
    	return instance;    
    }
}


或者
class Bank{
    private Bank(){
    }
    //注意是public final
    //在需要要这个类的对象时直接Bank bank1 = Bank.instance; 不需要getInstance()方法
    public static final Bank instance = new Bank();
}     
    1. 代码实现单例模式的懒汉式 ---目前线程不安全
class Bank{
    //1.私有化类的构造器
    private Bank(){
    }
    
    //2.内部创建类的对象
    private static Bank instance =  null;
    
    //3. 提供公共方法 返回类的对象
    public static Bank getInstance(){
        return instance==null? instance=new Bank():instance; 
        或者
        if(instance==null) instance = new Bank();
        return instance;
    }
}  
  • 类的属性赋值的位置有哪些,先后顺序为何?

    • 默认初始化
    • 显示初始化 / 构造器中初始化
    • 通过"对象.属性"或者“对象.方法”的方式赋值

abstract 抽象

    1. 可以用来修饰:类,方法
    1. 具体的:
    • abstract修饰类:抽象类

      • 此类不能实例化
      • 抽象类中一定有构造器,便于子类实例化时调用
      • 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作。--->抽象的使用前提:继承性
    • abstract修饰方法:抽象方法

      • 抽象方法只有方法的声明,没有方法体
      • 包含抽象方法的类,一定是一个抽象类(必须声明为abstract)。反之,抽象类可以没有抽象方法的。
      • 只有子类重写了父类的所有抽象方法后,此子类方可实例化.(包括直接父类和间接父类)
      • 若子类没有重写父类中所有的抽象方法,那么子类也是一个抽象类
    1. 注意点:
    • abstract不能用来修饰:属性,构造器等结构
    • abstract不能用来修饰private私有方法,静态static方法,final的方法,final的类
    • 没有抽象静态方法,static和abstract关键字不能共用。
      • 解释①:static方法不可以被重写。
      • 解释②:若能用static方法,则意味着可以通过类调这个方法。而类声明为abstract的目的就是为了不能调用这个抽象方法,而是通过子类重写方法,通过子类对象调用。现在又abstract和static,这不精分吗。
    • 抽象类中可以有非抽象的构造方法,创建子类的实例时可能会调用这些构造方法。抽象类不能被实例化,然而可以创建一个引用变量,其类型是一个抽象类,并让它引用非抽象的子类的一个实例。
    • 抽象类及抽象方法不能被final修饰符修饰。因为抽象类只有允许创建其子类,它的抽象方法才能被实现,并且只有它的具体子类才能被实例化,而用final修饰的类不允许拥有子类,用final修饰的方法不允许被子类覆盖。
    • 抽象方法不能被private修饰符修饰。(因为private的方法不可以被重写)
  • 举例

    • 举例1:

    • 技术分享图片

    • 举例2:IO流中涉及到的抽象类:InputStream/OutputStream/Reader/Writer在其内部定义了抽象的read(),write()方法public abstract int read() throws IOException;。因为读写的时候情况很多,不知道具体情况,所以写成抽象。

抽象类练习

题目要求

编写工资系统,实现不同类型员工(多态)的按月发放工资。

如果当月出现某个 Employee对象的生日,则将该雇员的工资增加100元。

实验说明:

(1)定义一个Employee类,该类包含: private成员变量name,number,birthday,其中birthday 为MyDate类的对象; abstract方法earnings(); toString()方法输出对象的name,number和birthday。

(2)MyDate类包含: private成员变量year,month,day ; toDateString()方法返回日期对应的字符串:xxxx年xx月xx日

(3)定义SalariedEmployee类继承Employee类,实现按月计算资的员工处理。该类包括:private成员变量monthlySalary; 实现父类的抽象方法earnings(),该方法返回monthlySalary值;toString()方法输 出员工类型信息及员工的name,number,birthday。 (4)参照SalariedEmployee类定义HourlyEmployee类,实现按小时计算工资的 员工处理。该类包括: private成员变量wage和hour; 实现父类的抽象方法earnings(),该方法返回wage*hour值; toString()方法输出员工类型信息及员工的name,number,birthday。

(5)定义PayrollSystem类,创建Employee变量数组并初始化,该数组存放各 类雇员对象的引用。利用循环结构遍历数组元素,输出各个对象的类 型,name,number,birthday,以及该对象生日。当键盘输入本月月份值时,如果本 月是某个Employee对象的生日,还要输出增加工资信息。

提示:

//定义People类型的数组People c1[]=new People[10];

//数组元素赋值 c1[0]=new People("John","0001",20); c1[1]=new People("Bob","0002",19);

//若People有两个子类Student和Officer,则数组元素赋值时,可以使父类类型的数组元素指向子类。

c1[0]=new Student("John","0001",20,85.0); c1[1]=new Officer("Bob","0002",19,90.5);

package com.shc.exer2;
/*
 * 实验说明:
	(1)定义一个Employee类,该类包含:
	private成员变量name,number,birthday,其中birthday 为MyDate类的对象;
	abstract方法earnings();
	toString()方法输出对象的name,number和birthday。
 */
public abstract class Employee {
	private String name;
	private int number;
	private MyDate birthday;
	
//	public Employee() {} //如果子类构造器时调用这个构造器的话,那么子类就无法对name,number,birthday进行初始化
	
	public Employee(String name, int number, MyDate birthday) {
		super();
		this.name = name;
		this.number = number;
		this.birthday = birthday;
	}

	public abstract double earning();

	@Override
	//toString()是返回字符串 不是自己输出字符串
	public String toString() {
		//因为这个方法一定是子类调用,所以没必要写那个Employee类的名字了
		return " [name=" + name + ", number=" + number + ", birthday="  + "]"+birthday.toDateString();//注意这里调用了MyDate类的birthday的toString方法
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

	public MyDate getBirthday() {
		return birthday;
	}

	public void setBirthday(MyDate birthday) {
		this.birthday = birthday;
	}
	
//	@Override
//	public String toString() {
//		return " [name="+name+", number="+number+", birthday="+birthday;
//	}	
}
package com.shc.exer2;
/*
 * 2)MyDate类包含:
private成员变量year,month,day ;
toDateString()方法返回日期对应的字符串:xxxx年xx月xx日
 */
public class MyDate {
	private int year;
	private int month;
	private int day;
	
	public String toDateString() {
		return year+"年"+month+"月"+day+"日";
	}

	public MyDate(int year, int month, int day) {
		super();
		this.year = year;
		this.month = month;
		this.day = day;
	}

	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getMonth() {
		return month;
	}

	public void setMonth(int month) {
		this.month = month;
	}

	public int getDay() {
		return day;
	}

	public void setDay(int day) {
		this.day = day;
	}
	
}
package com.shc.exer2;
/*
 * (3)定义SalariedEmployee类继承Employee类,实现按月计算工资的员工处理。
 * 该类包括:
 * private成员变量monthlySalary;
 * 实现父类的抽象方法earnings(),该方法返回monthlySalary值;
 * toString()方法输出员工类型信息及员工的name,number,birthday
 */
public class SalariedEmployee extends Employee{
	
	private double monthlySalary;
	
//	public SalariedEmployee() {}
	
	public SalariedEmployee(String name, int number, MyDate birthday, double monthlySalary) {
		super(name, number, birthday);
		this.monthlySalary = monthlySalary;
	}

	@Override
	public double earning() {
		// TODO Auto-generated method stub
		return monthlySalary;
	}
	
	public String toString() {
		return "SalariedEmployee: "+super.toString()+"]";
	}

	public double getMonthlySalary() {
		return monthlySalary;
	}

	public void setMonthlySalary(double monthlySalary) {
		this.monthlySalary = monthlySalary;
	}
}
package com.shc.exer2;
/*
 * 4)参照SalariedEmployee类定义HourlyEmployee类,实现按小时计算工资的
员工处理。该类包括:
private成员变量wage和hour;
实现父类的抽象方法earnings(),该方法返回wage*hour值;
toString()方法输出员工类型信息及员工的name,number,birthday。

 */
public class HourlyEmployee extends Employee{
	private double wage;
	private int hour;
	
	
	public HourlyEmployee(String name, int number, MyDate birthday) {
		super(name, number, birthday);
	}

	public HourlyEmployee(String name, int number, MyDate birthday, double wage, int hour) {
		super(name, number, birthday);
		this.wage = wage;
		this.hour = hour;
	}
	
	@Override
	public double earning() {
		return wage*hour;
	}
	
	@Override
	public String toString() {
		return "HourlyEmployee: "+super.toString()+"]";
	}

	public double getWage() {
		return wage;
	}

	public void setWage(double wage) {
		this.wage = wage;
	}

	public int getHour() {
		return hour;
	}

	public void setHour(int hour) {
		this.hour = hour;
    }	
}
package com.shc.exer2;

import java.util.Calendar;
import java.util.Scanner;

/*
 * 定义PayrollSystem类,创建Employee变量数组并初始化,该数组存放各类雇员对象的引用。
 * 利用循环结构遍历数组元素,输出各个对象的类型,name,number,birthday。
 * 当键盘输入本月月份值时,如果本月是某个Employee对象的生日,还要输出增加工资信息。

payroll	
n.	(公司员工的)工资名单; (公司的)工资总支出;
[例句]We have 500 people on the payroll.
我们在编员工有500人。
 */
public class PayrollSystem {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//方式一
//		Scanner in = new Scanner(System.in);//读入
//		System.out.println("请输入当月月份");
//		int month  = in.nextInt();
		
		//方式二 日期相关API
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);//获取当前日期
	//注意如果是用日历API的话,是从0月开始到11月	
	//所以比较的时候要month+1
		
		Employee[] employees = new Employee[2];
		employees[0]=new SalariedEmployee("shc", 201, new MyDate(2002, 4, 20), 100000);
		employees[1]=new HourlyEmployee("ywt", 202, new MyDate(2001,9,9), 60, 240);
		
		for(int i=0;i<employees.length;i++) {
			System.out.println(employees[i]);
			double salary = employees[i].earning();
			System.out.println("月工资为"+salary);
			if(month == employees[i].getBirthday().getMonth()) {
				System.out.println("生日快乐");
			}
		}	
	}
}
请输入当月月份
4
SalariedEmployee:  [name=shc, number=201, birthday=]2002年4月20日]
月工资为100000.0
生日快可乐
HourlyEmployee:  [name=ywt, number=202, birthday=]2001年9月9日]
月工资为14400.0

abstract应用:模板方法设计模式

  • 多态的应用
  • 抽象类体现的就是一种模板模式的设计,抽象类作为多各自类的通用模板,子类在抽象类的基础上进行扩展,改造,但子类总体上会保留抽象类的行为方式。
  • 解决的问题
    • 当功能内部一部分实现是确定的,一部分实现是不确定的。这是可以把不确定的部分暴露出去,让子类去实现。
    • 换句话说,在软件开发中实现一个算法时,整体步骤很固定,通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。
  • 实际应用
  • 模板方法设计模式是编程中经常用得到的模式。各个框架、类库中都有他的 影子,
  • 比如常见的有:
  • ? 数据库访问的封装
  • ? Junit单元测试
  • ? JavaWeb的Servlet中关于doGet/doPost方法调用
  • ? Hibernate中模板程序
  • ? Spring中JDBCTemlate、HibernateTemplate等
  • 举例
package com.shc.java1;
/*
 * 抽象里的应用
 * code()那部分
 */
public class TemplateTest {
	public static void main(String[] args) {
		SubTemplate s = new SubTemplate();
		s.spendTime();
	}
}

abstract class Template{
	//计算某个方法执行所花时间
	public void spendTime() {
		long start = System.currentTimeMillis();
		code(); //不确定的部分,易变的部分
		long end = System.currentTimeMillis();
		System.out.println(end-start);
	}
	public abstract void code();
}

class SubTemplate extends Template{
	@Override
	public void code() {
		for(int i=0;i<1000000;i++) {if(i>100)i=i; }
	}
}
--------------------------
3    ```

```java
package com.shc.java1;
//抽象类的应用:模板方法的设计模式
public class TemplateMethodTest {

	public static void main(String[] args) {
		BankTemplateMethod btm = new DrawMoney();
		btm.process();

		BankTemplateMethod btm2 = new ManageMoney();
		btm2.process();
	}
}
abstract class BankTemplateMethod {
	// 具体方法
	public void takeNumber() {
		System.out.println("取号排队");
	}

	public abstract void transact(); // 办理具体的业务 //钩子方法

	public void evaluate() {
		System.out.println("反馈评分");
	}

	// 模板方法,把基本操作组合到一起,子类一般不能重写
	public final void process() {
		this.takeNumber();

		this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码

		this.evaluate();
	}
}

class DrawMoney extends BankTemplateMethod {
	public void transact() {
		System.out.println("我要取款!!!");
	}
}

class ManageMoney extends BankTemplateMethod {
	public void transact() {
		System.out.println("我要理财!我这里有2000万美元!!");
	}
}    

interface 接口

  • 接口的使用
package com.shc.java2;
/*
 * 接口的使用
 * 1. 接口使用interface来定义
 * 2. Java中,接口和类是两个并列的结构
 * 3. 如何定义接口,定义接口中的成员
 * 		3.1 JDk7:以前,只能定义全局常量和抽象方法
 * 			全局常量:public static final  static:只有一份 final:不变的   但是书写时可以省略不写
 * 			抽象方法:public abstract		
 * 		3.2 JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法(略)
 * 
 * 4. 接口中不能定义构造器!
 * 		意味着接口不可以被实例化。(所以子类实例化时不会调用到接口)
 * 5. Java开发中,接口通过让类去实现(implements)的方式来使用
 * 	  如果此实现类覆盖了接口中的所有抽象方法,则此类可以实例化。
 * 	  如果此实现类没有覆盖了接口中的所有抽象方法,则此类仍要声明为abstract。
 * 6. 实现 --- 小三角是空心
 * 7. Java类可以实现多个接口 -->弥补了Java单继承性的局限性
 *    格式:class AA extends BB implements CC,DD,EE
 * 8. 接口和接口之间也叫继承关系,并且可以多继承
 体会
 * 9. 接口的使用可以体现多态性
 * 10. 接口,实际上可以看作一种规范
 * 11. 开发中,体会面向接口编程!
 * proxy
	n.	代理权; 代表权; 代理人; 受托人; 代表; (测算用的)代替物,指标;
	[例句]Your proxy will need to sign the form on your behalf.
	你的代理人将须代表你在表格上签字。
	[其他]	复数:proxies

 * 面试题:抽象类和接口有哪些异同?
 * 
 */
public class InterfaceTest {
	public static void main(String[] args) {
		System.out.println(Flyable.a);
//		Flyable.a=1;The final field Flyable.a cannot be assigned
	}
}


interface Flyable{
	//全局常量
	public static final int MAX_SPEED = 7900;
	public static final int MIN_SPEED = 1;
	int a = 5;//省略了public static final 但仍然是一个全局常量
	
	//抽象方法
	public abstract void fly();
	//省略了public abstract
	void stop();
}


interface Attach{
	public abstract void attach();
}

//如果没有实现接口中的全部抽象方法,此类就要声明为abstract
abstract class plane implements Flyable{

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("plane fly");
	}

//	@Override
//	public void stop() {
//		// TODO Auto-generated method stub
//		System.out.println("plane stop");
//	}
	
}

 class Bullet implements Flyable,Attach{

	@Override
	public void attach() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		
	}
	
}

/**************************************************/

interface AA{
	
}

interface CC{
	
}

interface DD extends AA,CC{
}  
  • 接口应用举例

    • 技术分享图片

    • Java应用程序 -- 调JDBC --- 通过JDBC来调数据库。

      JDBC可以理解为Java语言去操作数据库的技术。为什么没把JDBC和Java语言基础合在一起? 因为JDBC里定义了大量的接口。JDBC定了很多如何操作数据库的规范。

      那么为什么要定义这些规范?因为如果不定义规范的话,不同数据库的操作函数大不相同,量也多。所以Sun公司统一了一套标准规范(抽象的)(规范)(具体如何写由程序员决定)。

      编写代码时写的参数就是接口。所以Java程序员目前不是面向数据库编程,而是面向接口编程。在代码中不会看见某一个具体数据库的API。

      面向接口编程:我们在应用程序中,调用的结构都是JDBC中定义的接口,不会出现某一个数据库厂商的API

  • USB接口练习

package com.shc.java2;


/*
 * 接口的使用
 * 1. 接口的使用上体现多态性 。(函数的父类形参接收子类对象)
 * 2. 开发中,面向接口编程
 */
public class USBTest {
	public static void main(String[] args) {
		Computer computer = new Computer();
		//1. 创建了接口的非匿名实现了的非匿名对象
		Flash flash = new Flash();
		computer.transferDate(flash);//多态
		System.out.println("*****");
		//2. 创建了接口的非匿名实现类的匿名类对象
		computer.transferDate(new Flash());
		System.out.println("*****");
		//3. 创建了接口的匿名实现类的非匿名类对象
		USB usb = new USB() {

			@Override
			public void start() {
				// TODO Auto-generated method stub
			}

			@Override
			public void stop() {
				// TODO Auto-generated method stub
			}
		};
		computer.transferDate(usb);
		System.out.println("********");
		//4. 创建了接口的匿名实现类的匿名类对象
		computer.transferDate(new USB(){
			@Override
			public void start() {
				System.out.println("匿名start");
			}

			@Override
			public void stop() {
				System.out.println("匿名stop");
			}
		});
	}
}

interface USB{
	public abstract void start();
	
	public abstract void stop();
}


class Computer{
	public void transferDate(USB usb){
		usb.start();
		
		System.out.println("具体传输数据的细节");
		
		usb.stop();
	}
}

class Flash implements USB{

	@Override
	public void start() {
		// TODO Auto-generated method stub
		System.out.println("Flash start");
	}
	@Override
	public void stop() {
		// TODO Auto-generated method stub
		System.out.println("Flash stop");
	}
}

class Printer implements USB{

	@Override
	public void start() {
		// TODO Auto-generated method stub
		System.out.println("Printer start");
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		System.out.println("Printer stop");
	}
	
}
  • 面试题
interface A {
	int x = 0;
}
class B {
	int x = 1;
}
class C extends B implements A {
	public void pX() {
	//	System.out.println(x); 报错 ambigious x 不明确的x
        //1. 父类合接口位于同一级别
        //2. 无super.super
        //3. 接口不是父类的父类
        syso(super.x); //1 输出的是B的1
        syso(A.x); //0 利用了interface中的属性是全局常量
	}
	public static void main(String[] args) {
		new C().pX();
	}
}
  • nt问题:父类和父类的父类有属性同名了怎么办?比如都有int x
    • 不会报错,当前类调用x时,调用的是父类中的x(离当前子类近的那个类的x)
interface Playable {
	void play();
}
interface Bounceable {
	void play();
}
interface Rollable extends Playable, Bounceable {
	Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
	private String name;
	public String getName() {
		return name;
	}
	public Ball(String name) {
		this.name = name;
	}
    //算重写了Playable和Bounceable中的play方法都重写了
	public void play() {
		ball = new Ball("Football");
		System.out.println(ball.getName());//!!这里错了!!! Rollable接口中的ball是public static final Ball ball 不能改变指向!
	}
}
  • 接口练习

定义一个接口用来实现两个对象的比较。

interface CompareObject{

? public int compareTo(Object o); //若返回值是 0 , 代表相等; 若为正数,代表当 前对象大;负数代表当前对象小

}

?定义一个Circle类,声明redius属性,提供getter和setter方法

?定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。在 ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半 径大小。

?定义一个测试类InterfaceTest,创建两个ComparableCircle对象,调用compareTo 方法比较两个类的半径大小。

package com.shc.exer4;
/*
 * 定义一个接口用来实现两个对象的比较。
?interface CompareObject{
	public int compareTo(Object o); 
	//若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
  }
 */
public interface ComparObject {
	public int compareTo(Object o);
	//若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
}
package com.shc.exer4;

public class Circle {
//	private double r;
	//新写法:
	private Double r;
	
	public Circle() {}
	public Circle(Double r) {
		this.r=r;
	}
	
	public Double getR() {
		return r;
	}
	public void setR(Double r) {
		this.r = r;
	}	
}
package com.shc.exer4;

public class ComparableCircle extends Circle implements ComparObject{
	
//	public ComparableCircle() {}
//	public ComparableCircle(double r) {
//		super(r);
//	}
//	
//	@Override
//	public int compareTo(Object o){
//		if(this==o) return 0;
//		if(o instanceof ComparableCircle) {
//			//错误的 因为会有精度损失
////			return (int)(this.getR()-((ComparableCircle)o).getR());
//			ComparableCircle t = (ComparableCircle) o; //向下转型 记得给一个强转运算符() 。向上转型不需要(),父类管子类,直接转就可以
//			if(super.getR()==t.getR()) return 0;
//			return super.getR()>t.getR() ? 1 : -1;
//			//this.getR() 和super.getR() 效果一样 因为子类没有重写父类的getR()
//		}
//		return 0; //只能这样了
//	}
	
	//另一种写法 调用Double包装类中的方法
	public ComparableCircle() {
		// TODO Auto-generated constructor stub
	}
	
	public ComparableCircle(Double r) {
		super(r);
	}
	
	@Override
	public int compareTo(Object o){
		if(this==o) {return 0;}
		if(o instanceof ComparableCircle) {
			ComparableCircle t = (ComparableCircle)o;
			//使用包装类中的方法
			return this.getR().compareTo(t.getR());
		}
		return -8;
	}
}
package com.shc.exer4;

public class InterfaceTest {
	public static void main(String[] args) {
		ComparableCircle c1 = new ComparableCircle(1.1); //自动装箱 double-->Double
		ComparableCircle c2 = new ComparableCircle(2.9);
		System.out.println(c1.compareTo(c2));
	}
}
-1

JDK1.8接口新特性

  • 举例1
package com.shc.jdk8;

public class SubClassTest{
	public static void main(String[] args) {
		SubClass s = new SubClass();
		//1. 接口中定义的静态方法只能通过接口来调用 有点像工具类了哈 都是静态方法
		//实现类看不到接口中的静态方法
//		s.method1();
		CompareA.mehtod1();
		
		//2. 通过实现类的对象可以实现接口中的默认方法
		//如果实现类中重写了接口中的默认方法,调用时,仍然调用重写以后的方法
		s.method();
		//3. 如果子类(或者实现类)继承的父类和实现的接口中声明了同名同参数身为方法,那么子类在没有重写此方法的情况下,调用的是父类中的方法
		//称为类优先原则(针对于方法来说)(上道面试题关于接口和父类中的属性重名的时候如果不指明会编译报错)
		
		//4.如果实现类实现了多个接口,而在这多个接口中定义了多个同名同参数的默认方法,那么在实现类没有重写此方法的情况下,报错。--->接口冲突
		//这就需要我们必须重写此方法
		
		//6.在接口的实现类中可以不用重写接口的方法,一定程度上接口越来越像类
		//以后看到API中的接口有默认的default方法,在实现子类中可以直接调用
		//接口中的方法除了abstract的主要都是default方法 静态static方法看到的少
	}
}

class SubClass extends SuperClass implements CompareA,CompareB{
	//接口中的抽象方法需要重写 static和default方法不需要重写
//	@Override
//	public void method3(){}
//	@Override
//	public void method4(){}
	
//	public void method() {} //可以重写接口中的default方法
	
	public void method5() {}
	//5. 如何在实现类的方法中调用父类和接口中被重写的方法
	public void myMthod() {
		method5(); //调用自己重写的方法
		super.method5(); //调用父类中二点方法
		CompareA.mehtod1(); //接口名调用静态方法
		CompareA.super.method();//接口名+super+default方法()
	}
}
package com.shc.jdk8;
/*
 * jdk8 除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
 * abstract修饰无方法体的抽象方法
 * static default修饰有方法体的方法
 */
public interface CompareA {
	
	//可以定义静态方法 即只能由接口调用 原先绝对不可以定义方法,现在向类靠近了
	//实现类看不到接口中的静态方法
	public static void mehtod1(){System.out.println("hh");}
	//声明默认方法
	public default void method2(){}
	//public可以省略
	default void method() {System.out.println("CompareA");}
//	
//	void method3();
//	//<->
//	public  abstract void method4();
}
package com.shc.jdk8;

public interface CompareB {
	public default void method() {System.out.println("CompareB");}
}

package com.shc.jdk8;

public class SuperClass {
	public void method() {
		System.out.println("SuperClass");
	}
	public void method5() {
	}
}
  • 举例2
package com.shc.java8;

public class Man extends Father implements Filial,Spoony{

	//如果没有继承父类的话,则必须重写help方法
	//虽然接口中没有抽象方法,但是Man还是必须要重写,因为两个接口的方法发生冲突
//	@Override
//	public void help() {
//		// TODO Auto-generated method stub
////		Filial.super.help(); //调用Filial接口的
////		Spoony.super.help(); //调用Spoony接口的
//		System.out.println("救谁呢");//重写方法做出决定 
//	}
	
	//如果继承了父类的话,则不用再重写,不会error,按照父类定义的即可
}

class Father{
	public void help() {
		System.out.println("救你妈");
	}
}

interface Filial{ //孝顺的
	default void help() {
		System.out.println("老妈,我来救你了");
	}
}

interface Spoony{//痴情的
	default void help() {
		System.out.println("媳妇,我来救你了");
	}
}

interface应用:代理模式(Proxy)

技术分享图片

  • demo1
package com.shc.java2;
/*
 * 接口的应用:代理模式
 */
public class NetWorkTest {
	public static void main(String[] args) {
		Server server = new Server();
		ProxyServer proxyServer = new ProxyServer(server);
		proxyServer.browse(); //调用代理类的方法,代理类在该方法中执行了被代理类要做的事情+代理类要多做的事情
	}
}

interface NetWork{
	public void browse();
}
//被代理类
class Server implements NetWork{

	@Override
	public void browse() {
		// TODO Auto-generated method stub
		System.out.println("真实的服务器访问网络");
	}
}
//代理类
class ProxyServer implements NetWork{
	
	private NetWork work; //接口引用变量 可以去管理覆盖了接口的对象
	
	public ProxyServer(NetWork work) {
		this.work = work;
	}
	
	@Override
	public void browse() {
		// TODO Auto-generated method stub
		check();
		System.out.println("*******");
		work.browse();
	}
	
	public void check() {
		System.out.println("联网之前的检查操作");
	}
}```

- **demo2**

```java
package com.shc.java2;
public class StaticProxyTest {

	public static void main(String[] args) {
		Star s = new Proxy(new RealStar());
		s.confer(); 		//经纪人面谈
		s.signContract();	//经纪人签合同
		s.bookTicket();		//经纪人订票
		s.sing();			//明星:歌唱~~~
		s.collectMoney();  //经纪人收钱
	}
}

interface Star {
	void confer();// 面谈

	void signContract();// 签合同

	void bookTicket();// 订票

	void sing();// 唱歌

	void collectMoney();// 收钱
}

class RealStar implements Star {

	//为了RealStar可以new对象 即便RealStar不会做这些方法 也要把这些接口中的方法全部覆盖 方法体中没有语句也可以
	public void confer() {
	}

	public void signContract() {
	}

	public void bookTicket() {
	}

	public void sing() {
		System.out.println("明星:歌唱~~~");
	}

	public void collectMoney() {
	}
}

class Proxy implements Star {
	private Star real;//被代理的对象

	public Proxy(Star real) {
		this.real = real;
	}

	//代理 去做real不能做的事情
	public void confer() {
		System.out.println("经纪人面谈");
	}

	public void signContract() {
		System.out.println("经纪人签合同");
	}

	public void bookTicket() {
		System.out.println("经纪人订票");
	}

	//代理 做只有real能做的事情
	public void sing() {
		real.sing();
	}

	public void collectMoney() {
		System.out.println("经纪人收钱");
	}
}
  • 应用举例

    • 应用场景:

      • 安全代理:屏蔽对真实角色的直接访问。

      • 远程代理:通过代理类处理远程方法调用(RMI)

      • 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象 比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有 100MB,在打开文件时,不可能将所有的图片都显示出来,这样就可以使用代理 模式,当需要查看图片时,用proxy来进行大图片的打开。 ?

    • 分类

      • 静态代理(静态定义代理类)
      • 动态代理(动态生成代理类)
        • JDK自带的动态代理,需要反射等知识

interface应用:工厂模式

拓展:工厂设计模式.pdf

    1. 解决问题::实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离 起来,达到提高灵活性的目的。
    1. 具体模式:
    • ? 简单工厂模式:用来生产同一等级结构中的任意产品。(对于增加新的产品, 需要修改已有代码)
    • ? 工厂方法模式:用来生产同一等级结构中的固定产品。(支持增加任意产品)
    • ? 抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无 能为力;支持增加产品族)

    接口的应用:工厂模式

    工厂模式:实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离 起来,达到提高灵活性的目的。

    其实设计模式和面向对象设计原则都是为了使得开发项目更加容易扩展和维 护,解决方式就是一个“分工”。

    社会的发展也是这样,分工越来越细。

    原始社会的人:人什么都要会,自己种,自己打猎,自己织衣服,

    自己治病 现在的人:可以只会一样,其他都不会,只会 Java 也能活,不会做饭,不会开 车,不会....

内部类

  • 局部内部类成员内部类在编译后都会对应生成.class文件
    • 局部内部类:外部类&内部类名.class
    • 成员内部类:外部类&数字 内部类名.class
    • 为什么会有外部类名?因为内部类需要依托于外部类
    • 技术分享图片
/*
 * 类的内部成员之五
 * 1. Java中允许将一个类声明在另一个类B中,则类A就是内部类,类B称为外部类
 * 
 * 2. 内部类的分类:成员内部类(静态,非静态) vs 局部内部类(方法内,代码块内,构造期内)
 * 
 * 3. 成员内部类的理解:
 * 		一方面,作为外部类的成员
 * 			》调用外部类结构
 * 			》可以被static修饰
 * 			》可以被4中不同的权限修饰符修饰
 * 		另一方面,作为一个类
 * 			》类内,可以定义属性,方法,构造器等
 * 			》可以被final修饰,表示此类不能被继承,言外之意,不使用final,就可以继承
 * 			》可以被abstract修饰	
 * 4. 关注以下3个问题即可
 * 		4.1 如何实例化成员内部类对象
            //创建静态的Bird实例(静态的成员内部类)
            Person.Bird pBird = new Person.Bird();
            //创建非静态的Dog实例(非静态的成员内部类) 
            Person p = new Person();
            Person.Dog dog = p.new Dog();
 * 		
 		4.2 如何在成员内部类中区分调用外部类的结构
 		class Person{
            String name = "ywt";
            class Dog{ //静态成员内部类
                String name="henry";
                public void display(String name) {
                    System.out.println(name);//形参
                    System.out.println(this.name);//内部类的属性
                    System.out.println(Person.this.name);//外部类的属性
                }
            }
        }
 * 		4.3 开发中局部内部类的使用,见《InnerClassTest1.java》
 * /
//4.3 开发中局部内部类的使用,见《InnerClassTest1.java》
//开发中常见:
	//返回一个实现了Comparable接口的类的对象
	public Comparable getComparable() {
		//为什么这个类不放在外面? 因为这个类只有这里面用
		//创建一个实现了Compparable接口的类
		//方式一:
//		class MyComparablex implements Comparable{
//			@Override
//			public int compareTo(Object o) {
//				// TODO Auto-generated method stub
//				return 0;
//			}
//		}
//		return new MyComparablex();
		
		//方式二: 创建并返回了匿名内部类的匿名对象
		return new Comparable() {
			@Override
			public int compareTo(Object o) {
				// TODO Auto-generated method stub
				return 0;
			}
			
		};
	}
  • 内部类常见问题:
package com.shc.java3;
/*
 * 移动端常见问题
 */
public class InnerTest2 {
	/*
	 * 在局部内部类的方法中(show()),如果调用局部内部类所声明的方法(比如method)中的局部变量的话(比如num)
	 * 要求此局部变量是一个final
	 * 
	 * jdk 7及以前的版本,要求此局部变量显示的声明为final的
	 * jdk 8及之后的版本,可以省略final的声明
	 */
	public void method() {
		//局部变量
		int num=10; //final int 
		class AA{
//			num=9;
			public void show() {
//				num=9; error
//Local variable num defined in an enclosing scope must be final or effectively final
//				在封闭作用域中定义的局部变量num必须是final或有效final
			//在内部类中使用外部类的属性成员只能使用不能修改,因为只是从外部类传入了一个副本
			//原因:虽然在语法上小的作用域覆盖大的作用域,但是在编译产生.class文件时,外部类和内部类是分别产生了两个.class文件
			//(方法存在于外部类)
//			//如果在内部类中修改了这个元素,那么在那个.class文件中也需要修改,不好修改。
				System.out.println(num);
			}
		}
	}
}

每天一考

    1. abstract能修饰那些结构?修饰以后,有什么特点?
    • 类,方法。
      • 记得总结final,static,abstract
    • 类不能实例化,提供子类,子类去实例化。
    • 抽象方法:只定义了一种功能的标准,需要子类去实现。
    1. 接口是否能继承接口?抽象类是否能实现(implements)接口?抽象类是否能继承非抽象的类?
    • ①能 ②能 ③能
    1. 声明抽象类,并包含抽象方法。测试类中创建一个继承抽象类的匿名子类的对象。
    • abstract AA{    
      	public abstract void f();
      }
      public class test{
      	main{
      		AA f = new AA(){
      			@Override            
      			public void abstract(){}         
      		}    
      	}
      }
      
    1. 抽象类和接口有那些共同点和区别?
    • 相同点
      • 都可以被继承
    • 不同点:
      • 抽象类:有构造器。单继承。类体系。
      • 接口:不能声明构造器。多继承。接口体系。
    • 技术分享图片
    1. 如何创建静态成员内部类和非静态成员内部类的对象?

      Person static Dog Bird

    //创建静态不用new p
    Person.Dog = new Persin.Dog();
    //创建非静态要new p。因为没有p对象就无法new Bird()
    Person p = new Person();
    Person.Bird bird = new p.new Person.Bird();
    

Java面向对象(下)

原文:https://www.cnblogs.com/4-Prestar/p/14762681.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!