01、关键字:static 1.1、static 的使用 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过 new 关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。
我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份。
例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public class StaticTest { public static void main (String[] args) { Chinese.nation = "中国" ; Chinese c1 = new Chinese (); c1.name = "姚明" ; c1.age = 40 ; c1.nation = "CHN" ; Chinese c2 = new Chinese (); c2.name = "马龙" ; c2.age = 30 ; c2.nation = "CHINA" ; System.out.println(c1.nation); } }class Chinese { String name; int age; static String nation; }
1.2、类变量 vs 实例变量内存解析
1.3、static 修饰方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 public class StaticTest { public static void main (String[] args) { Chinese.nation = "中国" ; Chinese c1 = new Chinese (); c1.eat(); Chinese.show(); } }class Chinese { String name; int age; static String nation; public void eat () { System.out.println("中国人吃中餐" ); this .info(); System.out.println("name : " + name); walk(); System.out.println("nation : " + Chinese.nation); } public static void show () { System.out.println("我是一个中国人!" ); System.out.println(Chinese.nation); walk(); } public void info () { System.out.println("name : " + name + ",age : " + age); } public static void walk () { } }
1.4、自定义 ArrayUtil 的优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 public class ArrayUtil { public static int getMax (int [] arr) { int maxValue = arr[0 ]; for (int i = 1 ; i < arr.length; i++) { if (maxValue < arr[i]) { maxValue = arr[i]; } } return maxValue; } public static int getMin (int [] arr) { int minValue = arr[0 ]; for (int i = 1 ; i < arr.length; i++) { if (minValue > arr[i]) { minValue = arr[i]; } } return minValue; } 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 avgValue = getSum(arr) / arr.length; return avgValue; } public static void reverse (int [] arr) { for (int i = 0 ; i < arr.length / 2 ; i++) { int temp = arr[i]; arr[i] = arr[arr.length - i - 1 ]; arr[arr.length - i - 1 ] = temp; } } public void reverse (String[] arr) { } 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 null ; } public static void sort (int [] arr) { 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 ]) { swap(arr,j ,j+1 ); } } } } private static void swap (int [] arr,int i,int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void print (int [] arr) { System.out.print("[" ); for (int i = 0 ; i < arr.length; i++) { System.out.print(arr[i] + "," ); } System.out.println("]" ); } public static int getIndex (int [] arr, int dest) { for (int i = 0 ; i < arr.length; i++) { if (dest==arr[i]) { return i; } } return -1 ; } }
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class ArrayUtilTest { public static void main (String[] args) { int [] arr = new int []{32 ,5 ,26 ,74 ,0 ,96 ,14 ,-98 ,25 }; int max = ArrayUtil.getMax(arr); System.out.println("最大值为:" + max); System.out.print("排序前:" ); ArrayUtil.print(arr); ArrayUtil.sort(arr); System.out.print("排序后:" ); ArrayUtil.print(arr); } }
1.5、static 的应用举例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public class CircleTest { public static void main (String[] args) { Circle c1 = new Circle (); Circle c2 = new Circle (); Circle c3 = new Circle (); System.out.println("c1 的 ID:" + c1.getId()); System.out.println("c2 的 ID:" + c2.getId()); System.out.println("c3 的 ID:" + c3.getId()); System.out.println("创建圆的个数: " + Circle.getTotal()); } }class Circle { private double radius; private int id; public Circle () { id = init++; total++; } public Circle (double radius) { this (); this .radius = radius; } private static int total; private static int init = 1001 ; public double findArea () { return 3.14 * radius * radius; } public double getRadius () { return radius; } public void setRadius (double radius) { this .radius = radius; } public int getId () { return id; } public static int getTotal () { return total; } }
1.6、static 的练习 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 public class Account { private int id; private String pwd = "000000" ; private double balance; private static double interestRate; private static double minMoney = 1.0 ; private static int init = 1001 ; public Account () { id = init++; } public Account (String pwd,double balance) { id = init++; this .pwd = pwd; this .balance = balance; } public String getPwd () { return pwd; } public void setPwd (String pwd) { this .pwd = pwd; } public static double getInterestRate () { return interestRate; } public static void setInterestRate (double interestRate) { Account.interestRate = interestRate; } public static double getMinMoney () { return minMoney; } public static void setMinMoney (double minMoney) { Account.minMoney = minMoney; } public int getId () { return id; } public double getBalance () { return balance; } @Override public String toString () { return "Account [id=" + id + ", pwd=" + pwd + ", balance=" + balance + "]" ; } }
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class AccountTest { public static void main (String[] args) { Account acct1 = new Account (); Account acct2 = new Account ("qwerty" ,2000 ); Account.setInterestRate(0.012 ); Account.setMinMoney(100 ); System.out.println(acct1); System.out.println(acct2); System.out.println(acct1.getInterestRate()); System.out.println(acct1.getMinMoney()); } }
1.7、单例(Singleton)设计模式 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。 设计模免去我们自己再思考和摸索。就像是经典的棋谱,不同的棋局,我们用不同的棋谱。”套路”
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例 。并且该类只提供一个取得其对象实例的方法。如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为 private ,这样,就不能用 new 操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。
1、单例模式的饿汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public class SingletonTest { public static void main (String[] args) { Bank bank1 = Bank.getInstance(); Bank bank2 = Bank.getInstance(); System.out.println(bank1 == bank2); } }class Bank { private Bank () { } private static Bank instance = new Bank (); public static Bank getInstance () { return instance; } }
2、单例模式的懒汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class SingletonTest2 { public static void main (String[] args) { Order order1 = Order.getInstance(); Order order2 = Order.getInstance(); System.out.println(order1 == order2); } }class Order { private Order () { } private static Order instance = null ; public static Order getInstance () { if (instance == null ){ instance = new Order (); } return instance; } }
3、单例模式的优点
由于单例模式只生成一个实例,减少了系统性能开销 ,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
4、单例(Singleton)设计模式-应用场景
网站的计数器 ,一般也是单例模式实现,否则难以同步。应用程序的日志应用 ,一般都使用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。数据库连接池 的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。项目中,读取配置文件的类 ,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取。 Application 也是单例的典型应用Windows 的 Task Manager (任务管理器) 就是很典型的单例模式 Windows 的 Recycle Bin(回收站) 也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。 02、理解 main 方法的语法(了解) 由于 Java 虚拟机需要调用类的 main()方法,所以该方法的访问权限必须是 public,又因为 Java 虚拟机在执行 main()方法时不必创建对象,所以该方法必须是 static 的,该方法接收一个 String 类型的数组参数,该数组中保存执行 Java 命令时传递给所运行的类的参数。
又因为 main() 方法是静态的,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,这种情况,我们在之前的例子中多次碰到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class MainTest { public static void main (String[] args) { Main.main(new String [100 ]); MainTest test = new MainTest (); test.show(); } public void show () { } }class Main { public static void main (String[] args) { args = new String [100 ]; for (int i = 0 ;i < args.length;i++){ args[i] = "args_" + i; System.out.println(args[i]); } } }
命令行参数用法举例
1 2 3 4 5 6 7 8 public class MainDemo { public static void main (String[] args) { for (int i = 0 ;i < args.length;i++){ System.out.println("/*/*/*/" + args[i]); } } }
//运行程序 MainDemo.java
1 2 javac MainDemo.java java MainDemo “Tom” “Jerry” “Shkstart”
03、类的成员之四:代码块static 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 public class BlockTest { public static void main (String[] args) { String desc = Person.desc; System.out.println(desc); Person p1 = new Person (); Person p2 = new Person (); System.out.println(p1.age); Person.info(); } }class Person { String name; int age; static String desc = "我是一个青年" ; public Person () { } static { System.out.println("hello,static block-1" ); desc = "我是一个爱小说的人" ; info(); } static { System.out.println("hello,static block-2" ); } { System.out.println("hello,block-2" ); } { System.out.println("hello,block-1" ); age = 1 ; eat(); desc = "我是一个爱小说的人 1" ; info(); } public Person (String name,int age) { this .name = name; this .age = age; } public void eat () { System.out.println("吃饭" ); } @Override public String toString () { return "Person [name=" + name + ", age=" + age + "]" ; } public static void info () { System.out.println("我是一个快乐的人。" ); } }
静态初始化块举例 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 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 () { System.out.println("Mid 的无参数的构造器" ); } public Mid (String msg) { this (); System.out.println("Mid 的带参数构造器,其参数值:" + msg); } }class Leaf extends Mid { static { System.out.println("Leaf 的静态初始化块" ); } { System.out.println("Leaf 的普通初始化块" ); } public Leaf () { super ("尚硅谷" ); System.out.println("Leaf 的构造器" ); } }public class LeafTest { public static void main (String[] args) { new Leaf (); } }
静态初始化块举例 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Father { static { System.out.println("11111111111" ); } { System.out.println("22222222222" ); } public Father () { System.out.println("33333333333" ); } }public class Son extends Father { static { System.out.println("44444444444" ); } { System.out.println("55555555555" ); } public Son () { System.out.println("66666666666" ); } public static void main (String[] args) { System.out.println("77777777777" ); System.out.println("************************" ); new Son (); System.out.println("************************" ); new Son (); System.out.println("************************" ); new Father (); } }
总结:程序中成员变量赋值的执行顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class OrderTest { public static void main (String[] args) { Order order = new Order (); System.out.println(order.orderId); } }class Order { int orderId = 3 ; { orderId = 4 ; } }
04、关键字:final 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 public class FinalTest { final int WIDTH = 0 ; final int LEFT; final int RIGHT; { LEFT = 1 ; } public FinalTest () { RIGHT = 2 ; } public FinalTest (int n) { RIGHT = n; } public void dowidth () { } public void show () { final int NUM = 10 ; } public void show (final int num) { System.out.println(num); } public static void main (String[] args) { int num = 10 ; num = num + 5 ; FinalTest test = new FinalTest (); test.show(10 ); } }final class FianlA { }class AA { public final void show () { } }
1、面试题1
1 2 3 4 5 public class Something { public int addOne (final int x) { return ++x; } }
2、面试题2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Something { public static void main (String[] args) { Other o = new Other (); new Something ().addOne(o); } public void addOne (final Other o) { o.i++; } }class Other { public int i; }
05、抽象类与抽象方法abstract 随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 public class AbstractTest { public static void main (String[] args) { } }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 void walk () { System.out.println("人走路" ); } }class Student extends Person { public Student (String name,int age) { super (name,age); } public void eat () { System.out.println("学生应该多吃有营养的。" ); } @Override public void breath () { System.out.println("学生应该呼吸新鲜的无雾霾空气" ); } }
5.1、抽象类应用 抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。
问题:卡车(Truck)和驳船(RiverBarge)的燃料效率和行驶距离的计算方法完全不同。Vehicle 类不能提供计算方法,但子类可以。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public abstract class Vehicle { public abstract double calcFuelEfficiency () ; public abstract double calcTripDistance () ; }public class Truck extends Vehicle { public double calcFuelEfficiency () { } public double calcTripDistance () { } }public class RiverBarge extends Vehicle { public double calcFuelEfficiency () { } public double calcTripDistance ( ) { } }
5.2、练习 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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 () ; }
Manager 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Manager extends Employee { private double bonus; public Manager (double bonus) { super (); this .bonus = 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 类
1 2 3 4 5 6 7 8 public class CommonEmployee extends Employee { @Override public void work () { System.out.println("员工在一线车间生产产品。" ); } }
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class EmployeeTest { public static void main (String[] args) { Employee manager = new Manager ("库克" ,1001 ,5000 ,50000 ); manager.work(); CommonEmployee commonEmployee = new CommonEmployee (); commonEmployee.work(); } }
5.3、创建抽象类的匿名子类对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class Num { }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 void walk () { System.out.println("人走路" ); } }class Student extends Person { public Student (String name,int age) { super (name,age); } public Student () { } public void eat () { System.out.println("学生应该多吃有营养的。" ); } @Override public void breath () { System.out.println("学生应该呼吸新鲜的无雾霾空气" ); } }
PersonTest 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public class PersonTest { public static void main (String[] args) { method(new Student ()); Worker worker = new Worker (); method1(worker); method1(new Worker ()); System.out.println("*********************" ); Person p = new Person (){ @Override public void eat () { System.out.println("吃东西" ); } @Override public void breath () { System.out.println("呼吸空气" ); } }; method1(p); System.out.println("**********************" ); method1(new Person (){ @Override public void eat () { System.out.println("吃零食" ); } @Override public void breath () { System.out.println("云南的空气" ); } }); } public static void method1 (Person p) { p.eat(); p.walk(); } public static void method (Student s) { } }class Worker extends Person { @Override public void eat () { } @Override public void breath () { } }
5.4、多态的应用:模板方法设计模式(TemplateMethod) 抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。
解决的问题:
当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。 换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。
1、例 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public class TemplateTest { public static void main (String[] args) { SubTemlate t = new SubTemlate (); t.sendTime(); } }abstract class Template { public void sendTime () { long start = System.currentTimeMillis(); code(); long end = System.currentTimeMillis(); System.out.println("花费的时间为:" + (end - start)); } public abstract void code () ; }class SubTemlate extends Template { @Override public void code () { for (int i = 2 ;i <= 1000 ;i++){ boolean isFlag = true ; for (int j = 2 ;j <= Math.sqrt(i);j++){ if (i % j == 0 ){ isFlag = false ; break ; } } if (isFlag){ System.out.println(i); } } } }
2、例 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 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 万美元!!" ); } }
模板方法设计模式是编程中经常用得到的模式。各个框架、类库中都有他的影子,比如常见的有:
数据库访问的封装 Junit 单元测试 JavaWeb 的 Servlet 中关于 doGet/doPost 方法调用 Hibernate 中模板程序 Spring 中 JDBCTemlate、HibernateTemplate 等 5.5、抽象类的练习
1、Employee 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public abstract class Employee { private String name; private int number; private MyDate birthday; public Employee (String name, int number, MyDate birthday) { super (); this .name = name; this .number = number; this .birthday = birthday; } 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; } public abstract double earnings () ; @Override public String toString () { return "name=" + name + ", number=" + number + ", birthday=" + birthday.toDateString() + "]" ; } }
2、MyDate 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public class MyDate { private int year; private int month; private int 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; } public String toDateString () { return year + "年" + month + "月" + day + "日" ; } }
3、SalariedEmployee 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class SalariedEmployee extends Employee { private double monthlySalary; public SalariedEmployee (String name,int number,MyDate birthday) { super (name,number,birthday); } public SalariedEmployee (String name, int number, MyDate birthday, double monthlySalary) { super (name, number, birthday); this .monthlySalary = monthlySalary; } @Override public double earnings () { return monthlySalary; } @Override public String toString () { return "SalariedEmployee [" + super .toString() + "]" ; } }
4、HourlyEmployee 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class HourlyEmployee extends Employee { private int wage; private int hour; public HourlyEmployee (String name, int number, MyDate birthday) { super (name, number, birthday); } public HourlyEmployee (String name, int number, MyDate birthday, int wage, int hour) { super (name, number, birthday); this .wage = wage; this .hour = hour; } @Override public double earnings () { return wage*hour; } public int getWage () { return wage; } public void setWage (int wage) { this .wage = wage; } public int getHour () { return hour; } public void setHour (int hour) { this .hour = hour; } public String toString () { return "HourlyEmployee[" + super .toString() + "]" ; } }
5、PayrollSystem 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.util.Calendar;import java.util.Scanner;public class PayrollSystem { public static void main (String[] args) { Calendar calendar = Calendar.getInstance(); int month = calendar.get(Calendar.MONTH); Employee[] emps = new Employee [2 ]; emps[0 ] = new SalariedEmployee ("马良" , 1002 ,new MyDate (1992 , 2 , 28 ),10000 ); emps[1 ] = new HourlyEmployee ("博西" , 2001 , new MyDate (1991 , 1 , 6 ),60 ,240 ); for (int i = 0 ;i < emps.length;i++){ System.out.println(emps[i]); double salary = emps[i].earnings(); System.out.println("月工资为:" + salary); if ((month+1 ) == emps[i].getBirthday().getMonth()){ System.out.println("生日快乐!奖励 100 元" ); } } } }
06、接口(interface) 6.1、概述 一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java 不支持多重继承。有了接口,就可以得到多重继承的效果。
另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又没有 is-a 的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打印机、扫描仪、摄像头、充电器、MP3 机、手机、数码相机、移动硬盘等都支持 USB 连接。
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要…则必须能…”的思想。继承是一个"是不是"的关系,而接口实现则是"能不能"的关系。
接口的本质是契约,标准,规范 ,就像我们的法律一样。制定好后大家都要遵守。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 public class InterfaceTest { public static void main (String[] args) { System.out.println(Flayable.MAX_SPEED); System.out.println(Flayable.MIN_SPEED); } }interface Flayable { public static final int MAX_SPEED = 7900 ; int MIN_SPEED = 1 ; public abstract void fly () ; void stop () ; }interface Attackable { void attack () ; }class Plane implements Flayable { @Override public void fly () { System.out.println("飞机通过引擎起飞" ); } @Override public void stop () { System.out.println("驾驶员减速停止" ); } }abstract class Kite implements Flayable { @Override public void fly () { } }class Bullet extends Object implements Flayable ,Attackable,CC{ @Override public void attack () { } @Override public void fly () { } @Override public void stop () { } @Override public void method1 () { } @Override public void method2 () { } }interface AA { void method1 () ; }interface BB { void method2 () ; }interface CC extends AA ,BB{ }
6.2、举例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 public class USBTest { public static void main (String[] args) { Computer com = new Computer (); Flash flash = new Flash (); com.transferData(flash); com.transferData(new Printer ()); USB phone = new USB (){ @Override public void start () { System.out.println("手机开始工作" ); } @Override public void stop () { System.out.println("手机结束工作" ); } }; com.transferData(phone); com.transferData(new USB (){ @Override public void start () { System.out.println("mp3 开始工作" ); } @Override public void stop () { System.out.println("mp3 结束工作" ); } }); } }class Computer { public void transferData (USB usb) { usb.start(); System.out.println("具体传输数据的细节" ); usb.stop(); } }interface USB { void start () ; 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("打印机结束工作" ); } }
6.3、接口的应用:代理模式(Proxy) 代理模式是 Java 开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 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 () { 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(); work.browse(); } }
应用场景:
安全代理:屏蔽对真实角色的直接访问。 远程代理:通过代理类处理远程方法调用(RMI) 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象 比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有 100MB,在打开文件时,不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用 proxy 来进行大图片的打开。
分类
静态代理(静态定义代理类) 动态代理(动态生成代理类) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 public class StaticProxyTest { public static void main (String[] args) { Proxy 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 { 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; } public void confer () { System.out.println("经纪人面谈" ); } public void signContract () { System.out.println("经纪人签合同" ); } public void bookTicket () { System.out.println("经纪人订票" ); } public void sing () { real.sing(); } public void collectMoney () { System.out.println("经纪人收钱" ); } }
6.4、接口的应用:工厂模式 拓展:工厂设计模式.pdf
接口和抽象类之间的对比
1 定义 包含抽象方法的类 主要是抽象方法和全局常量的集合 2 组成 构造方法、抽象方法、普通方法、常量、变量 常量、抽象方法、(jdk8.0:默认方法、静态方法) 3 使用 子类继承抽象类(extends) 子类实现接口(implements) 4 关系 抽象类可以实现多个接口 接口不能继承抽象类,但允许继承多个接口 5 常见设计模式 模板方法 简单工厂、工厂方法、代理模式 6 对象 都通过对象的多态性产生实例化对象 7 局限 抽象类有单继承的局限 接口没有此局限 8 实际 作为一个模板 是作为一个标准或是表示一种能力 9 选择 如果抽象类和接口都可以使用的话,优先使用接口,因为避免单继承的局限
在开发中,常看到一个类不是去继承一个已经实现好的类,而是要么继承抽象类,要么实现接口。 -【面试题】排错:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 interface A { int x = 0 ; }class B { int x = 1 ; }class C extends B implements A { public void pX () { System.out.println(x); } public static void main (String[] args) { new C ().pX(); } }
排错 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 interface Playable { void play () ; }interface Bounceable { void play () ; }interface Rollable extends Playable , Bounceable { Ball ball= new Ball ("PingPang" ); }public class Ball implements Rollable { private String name; public String getName () { return name; } public Ball (String name) { this .name= name; } public void play () { ball = new Ball ("Football" ); System.out.println(ball.getName()); } }
练习
CompareObject 类
1 2 3 4 5 6 7 8 9 public interface CompareObject { public int compareTo (Object o) ; }
Circle 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Circle { 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; } }
ComparableCircle 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class ComparableCircle extends Circle implements CompareObject { public ComparableCircle (double radius) { super (radius); } @Override public int compareTo (Object o) { if (this == o){ return 0 ; } if (o instanceof ComparableCircle){ ComparableCircle c = (ComparableCircle)o; return this .getRadius().compareTo(c.getRadius()); }else { return 0 ; } } }
InterfaceTest 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class InterfaceTest { public static void main (String[] args) { ComparableCircle c1 = new ComparableCircle (3.4 ); ComparableCircle c2 = new ComparableCircle (3.6 ); int compareValue = c1.compareTo(c2); if (compareValue > 0 ){ System.out.println("c1 对象大" ); }else if (compareValue < 0 ){ System.out.println("c2 对象大" ); }else { System.out.println("两个一样的" ); } int compareValue1 = c1.compareTo(new String ("AA" )); System.out.println(compareValue1); } }
07、Java 8 中关于接口的改进 Java 8 中,你可以为接口添加静态方法和默认方法。从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。
静态方法:
使用 static 关键字修饰。可以通过接口直接调用静态方法,并执行其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中找到像 Collection/Collections 或者 Path/Paths 这样成对的接口和类。
默认方法:
默认方法使用 default 关键字修饰。可以通过实现类对象来调用。我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。比如:java 8 API 中对 Collection、List、Comparator 等接口提供了丰富的默认方法。
例1
interface 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public interface CompareA { public static void method1 () { System.out.println("CompareA:西安" ); } public default void method2 () { System.out.println("CompareA:深圳" ); } default void method3 () { System.out.println("CompareA:杭州" ); } }
SubClassTest 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public class SubClassTest { public static void main (String[] args) { SubClass s = new SubClass (); CompareA.method1(); s.method2(); s.method3(); } }class SubClass extends SuperClass implements CompareA ,CompareB{ public void method2 () { System.out.println("SubClass:上海" ); } public void method3 () { System.out.println("SubClass:深圳" ); } public void myMethod () { method3(); super .method3(); CompareA.super .method3(); CompareB.super .method3(); } }
SuperClass 类
1 2 3 4 5 public class SuperClass { public void method3 () { System.out.println("SuperClass:北京" ); } }
CompareB 类
1 2 3 4 5 public interface CompareB { default void method3 () { System.out.println("CompareB:上海" ); } }
例2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 interface Filial { default void help () { System.out.println("老妈,我来救你了" ); } }interface Spoony { default void help () { System.out.println("媳妇,别怕,我来了" ); } }class Father { public void help () { System.out.println("儿子,救我媳妇!" ); } }class Man extends Father implements Filial , Spoony { @Override public void help () { System.out.println("我该就谁呢?" ); Filial.super .help(); Spoony.super .help(); } }
08、类的内部成员之五:内部类 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 public class InnerClassTest { public static void main (String[] args) { Person.Dog dog = new Person .Dog(); dog.show(); Person p = new Person (); Person.Bird bird = p.new Bird (); bird.sing(); System.out.println(); bird.display("喜鹊" ); } }class Person { String name = "李雷" ; int age; public void eat () { System.out.println("人,吃饭" ); } static class Dog { String name; int age; public void show () { System.out.println("卡拉是条狗" ); } } class Bird { String name = "杜鹃" ; public Bird () { } public void sing () { System.out.println("我是一只猫头鹰" ); Person.this .eat(); eat(); System.out.println(age); } public void display (String name) { System.out.println(name); System.out.println(this .name); System.out.println(Person.this .name); } } public void method () { class AA { } } { class BB { } } public Person () { class CC { } } }
InnerClassTest1类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public class InnerClassTest1 { public void method () { class AA { } } public Comparable getComparable () { return new Comparable (){ @Override public int compareTo (Object o) { return 0 ; } }; } }
8.1、匿名内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 interface Product { public double getPrice () ; public String getName () ; }public class AnonymousTest { public void test (Product p) { System.out.println("购买了一个" + p.getName() + ",花掉了" + p.getPrice()); } public static void main (String[] args) { AnonymousTest ta = new AnonymousTest (); ta.test(new Product (){ public double getPrice () { return 567.8 ; } public String getName () { return "AGP显卡" ; } }); } }
8.2、局部内部类的使用注意 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class InnerClassTest { public void method () { int num = 10 ; class AA { public void show () { System.out.println(num); } } } }