311.面向对象(下)-每天一考

1.如何实现向下转型?需要注意什么问题?如何解决此问题?

//Person p = new Man();
//使用强转符:()
Man m = (Man)p;
//可能ClassCastException异常。//使用instanceof在进行向下转型前判断。
if(p instanceof Man){Man m = (Man)p;
}

2.== 和 equals()有何区别?

3.重写其equals()方法

class User{String name;
int age;//重写其equals()方法public boolean equals(Object obj){if(obj == this){return true;}if(obj instanceof User){User u = (User)obj;return this.age == u.age && this.name.equals(u.name);}return false;}
}

4.写出8种基本数据类型及其对应的包装类

5.基本数据类型、包装类与String三者之间如何转换

自动装箱、自动拆箱
Integer i = 10;
基本数据类型、包装类—>String: valueOf(Xxx xx)
String—>基本数据类型、包装类:parseXxx(String s)

312.面向对象(下)-复习:多态性

为什么使用向下转型

有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用,因此向下转型。

如何实现向下转型

使用强制类型转换符:()

使用时的注意点

为了避免向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回ture就进行向下转型,如果返回false,不进行向下转型。

instanceof的使用

a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false
如果a instanceof A返回true,则a instanceof B也返回true,其中类B是类A的父类

谈谈你对多态性的理解

实现代码的通用性
抽象类和接口的使用肯定体现了多态性。(主要是因为抽象类、接口不能实例化)
类似Object类中定义的public boolean equals(Object obj)
String继承了Object类,重写了其中的equals方法,调用的时候可以直接传入子类的对象

多态是编译时行为还是运行时行为

运行时行为

313.面向对象(下)-复习:Object类及内部方法
314.面向对象(下)-复习:单元测试与包装类

static

315.面向对象(下)-static关键字的引入

当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上 的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象, 其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少 对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个 国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中 都单独分配一个用于代表国家名称的变量。

316.面向对象(下)-静态变量与实例变量的对比

package com.atguigu.java1;
/** static关键字的使用* * 1.static:静态的* 2.static可以用来修饰:属性、方法、代码块、内部类* * 3.使用static修饰属性:静态变量(或类变量)*        3.1 属性,按是否使用static修饰,又分为:静态属性  vs 非静态属性(实例变量)*            实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象中的*              非静态属性时,不会导致其他对象中同样的属性值的修改。*       静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致*              其他对象调用此静态变量时,是修改过了的。*        3.2 static修饰属性的其他说明:*            ① 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用*          ② 静态变量的加载要早于对象的创建。*          ③ 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。*          *          ④      类变量 实例变量*          类        yes     no*          对象     yes     yes*          *      3.3 静态属性举例:System.out; Math.PI;* * 4.使用static修饰方法:静态方法*      ① 随着类的加载而加载,可以通过"类.静态方法"的方式进行调用*       ②           静态方法    非静态方法*          类       yes     no*          对象     yes     yes*        ③ 静态方法中,只能调用静态的方法或属性*        非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性* * 5. static注意点:*    5.1 在静态的方法内,不能使用this关键字、super关键字*    5.2 关于静态属性和静态方法的使用,大家都从生命周期的角度去理解。*    * 6. 开发中,如何确定一个属性是否要声明为static的?*      > 属性是可以被多个对象所共享的,不会随着对象的不同而不同的。*      > 类中的常量也常常声明为static* *    开发中,如何确定一个方法是否要声明为static的?*      > 操作静态属性的方法,通常设置为static的*      > 工具类中的方法,习惯上声明为static的。 比如:Math、Arrays、Collections*/
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);//编译不通过
//      Chinese.name = "张继科";c1.eat();Chinese.show();//编译不通过
//      Chinese.eat();
//      Chinese.info();}
}
//中国人
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 : " + nation);}public static void show(){System.out.println("我是一个中国人!");//不能调用非静态的结构
//      eat();
//      name = "Tom";//可以调用静态的结构System.out.println(Chinese.nation);walk();}public void info(){System.out.println("name :" + name +",age : " + age);}public static void walk(){}
}

317.面向对象(下)-static修饰属性的其它说明

318.面向对象(下)-类变量和实例变量的内存解析

栈:局部变量
堆:new出来的结构:对象、数组
方法区:类的加载信息、静态域、常量池

319.面向对象(下)-static修饰方法
320.面向对象(下)-属性或方法是否应该static的经验之谈
321.面向对象(下)-自定义ArrayUtil工具类的优化

322.面向对象(下)-static的应用举例

package com.atguigu.java1;
//static关键字的应用
public class CircleTest {public static void main(String[] args) {       Circle c1 = new Circle();      Circle c2 = new Circle();      Circle c3 = new Circle(3.4);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();
//      id = init++;
//      total++;this.radius = radius;}private static int total;//记录创建的圆的个数private static int init = 1001;//static声明的属性被所有对象所共享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;}}

323.面向对象(下)-static课后练习:账户信息

package com.atguigu.exer;
/** 编写一个类实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,* 定义封装这些属性的方法。账号要自动生成。编写主类,使用银行账户类,输入、输出3个储户的上述信息。考虑:哪些属性可以设计成static属性。*/
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;//用于自动生成id使用的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;}@Overridepublic String toString() {return "Account [id=" + id + ", pwd=" + pwd + ", balance=" + balance + "]";}
}
package com.atguigu.exer;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());}
}

单例模式

324.面向对象(下)-设计模式与单例设计模式

设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、 以及解决问题的思考方式。设计模免去我们自己再思考和摸索。就像是经典 的棋谱,不同的棋局,我们用不同的棋谱。”套路”

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

325.面向对象(下)-单例的饿汉式实现

package com.atguigu.java2;
/** 单例设计模式:* 1. 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。* * 2. 如何实现?*     饿汉式  vs 懒汉式* * 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.私有化类的构造器,不让外面new对象private Bank(){}//2.内部创建类的对象//4.要求此对象也必须声明为静态的private static Bank instance = new Bank();//3.提供公共的静态的方法,返回类的对象public static Bank getInstance(){return instance;}
}

326.面向对象(下)-单例的懒汉式实现

package com.atguigu.java2;
//单例模式的懒汉式实现
public class SingletonTest2 {public static void main(String[] args) {Order order1 = Order.getInstance();Order order2 = Order.getInstance();System.out.println(order1 == order2);    }
}class Order{//1.私有化类的构造器private Order(){   }//2.声明当前类对象,没有初始化//4.此对象也必须声明为static的private static Order instance = null;//3.声明public、static的返回当前类对象的方法public static Order getInstance(){     if(instance == null){         instance = new Order();        }return instance;}
}

327.面向对象(下)-饿汉式和懒汉式的对比

区分饿汉式 和 懒汉式
饿汉式:
坏处:对象加载时间过长。
好处:饿汉式是线程安全的

懒汉式:好处:延迟对象的创建。
目前的写法坏处:线程不安全。—>到多线程内容时,再修改

328.面向对象(下)-单例模式的使用场景

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

单例模式的应用场景
网站的计数器,一般也是单例模式实现,否则难以同步。
应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取。
Application 也是单例的典型应用
Windows的Task Manager(任务管理器)就是很典型的单例模式
Windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

329.面向对象(下)-理解main()方法的语法

由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public,又因为Java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的,该方法接收一个String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数。

又因为main() 方法是静态的,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,这种情况,我们在之前的例子中多次碰到。

main()方法的使用说明:
1.main()方法作为程序的入口
2.main()方法也是一个普通的静态方法
3.main()方法的形参可以作为我们与控制台交互的方式。(之前:使用Scanner)

330.面向对象(下)-类中代码块结构的使用

代码块(或初始化块)的作用:对Java类或对象进行初始化

代码块(或初始化块)的分类:
静态代码块:一个类中代码块若有修饰符, 则只能被static修饰,称为静态代码块(static block)
非静态代码块:没有使用static修饰的,为非静态代码块。

//static代码块通常用于初始化static的属性
class Person {public static int total;static {total = 100;//为total赋初值}…… //其它属性或方法声明
}

静态代码块:用static 修饰的代码块
1.可以有输出语句。
2.可以对类的属性、类的声明进行初始化操作。
3.不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
4.若有多个静态的代码块,那么按照从上到下的顺序依次执行。
5.静态代码块的执行要先于非静态代码块。
6.静态代码块随着类的加载而加载(执行),且只执行一次。

非静态代码块:没有static修饰的代码块
1.可以有输出语句。
2.可以对类的属性、类的声明进行初始化操作。
3.除了调用非静态的结构外,还可以调用静态的变量或方法。
4.若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
5.每次创建对象的时候,都会执行一次。且先于构造器执行。

package com.atguigu.java3;
/** 类的成员之四:代码块(或初始化块)* * 1. 代码块的作用:用来初始化类、对象* 2. 代码块如果有修饰的话,只能使用static.* 3. 分类:静态代码块  vs 非静态代码块* * 4. 静态代码块*     >内部可以有输出语句*      >随着类的加载而执行,而且只执行一次*      >作用:初始化类的信息*      >如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行*       >静态代码块的执行要优先于非静态代码块的执行*      >静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构* * 5. 非静态代码块*        >内部可以有输出语句*      >随着对象的创建而执行*         >每创建一个对象,就执行一次非静态代码块*         >作用:可以在创建对象时,对对象的属性等进行初始化*         >如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行*      >非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法*/
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(){}public Person(String name,int age){this.name = name;this.age = age;}//非static的代码块{System.out.println("hello, block - 2");}{System.out.println("hello, block - 1");//调用非静态结构age = 1;eat();//调用静态结构desc = "我是一个爱学习的人1";info();}//static的代码块static{System.out.println("hello,static block-2");}static{System.out.println("hello,static block-1");//调用静态结构desc = "我是一个爱学习的人";info();//不可以调用非静态结构
//      eat();
//      name = "Tom";}//方法public void eat(){System.out.println("吃饭");}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}public static void info(){System.out.println("我是一个快乐的人!");}
}

331.面向对象( 下)-开发代码中代码块的使用举例

静态代码块的使用场景

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.apache.commons.dbutils.DbUtils;
import com.atguigu.connection.DBCPTest;
import com.mchange.v2.c3p0.ComboPooledDataSource;public class JDBCUtils {private static DataSource dataSource = null;static{InputStream is = null;try {is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");Properties pros = new Properties();pros.load(is);//调用BasicDataSourceFactory的静态方法,获取数据源。dataSource = BasicDataSourceFactory.createDataSource(pros);} catch (Exception e) {e.printStackTrace();}finally{if(is != null){try {is.close();} catch (IOException e) {e.printStackTrace();}}}}//使用DBCP数据库连接池实现数据库的连接public static Connection getConnection2() throws SQLException{Connection conn = dataSource.getConnection();System.out.println(conn);return conn;}
}

332.面向对象(下)-代码块的课后练习

LeafTest

package com.atguigu.java3;
//总结:由父及子,静态先行
class Root{static{System.out.println("Root的静态初始化块");}{System.out.println("Root的普通初始化块");}public Root(){super();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 LeafTest{public static void main(String[] args){new Leaf(); System.out.println();new Leaf();}
}

Son

package com.atguigu.java3;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();}}

333.面向对象(下)-属性赋值的先后顺序(完结篇)

334.面向对象(下)-final修饰类和方法

在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。

final标记的类不能被继承。提高安全性,提高程序的可读性。
String类、System类、StringBuffer类

final标记的方法不能被子类重写。
比如:Object类中的getClass()。

final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只能被赋值一次。
final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋 值,然后才能使用。
final double MY_PI = 3.14;

package com.atguigu.java3;
/** final:最终的* * 1. final可以用来修饰的结构:类、方法、变量* * 2. final 用来修饰一个类:此类不能被其他类所继承。*          比如:String类、System类、StringBuffer类* * 3. final 用来修饰方法:表明此方法不可以被重写*             比如:Object类中getClass();* * 4. final 用来修饰变量:此时的"变量"就称为是一个常量*      4.1 final修饰属性:可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化*       4.2 final修饰局部变量:*           尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值*           以后,就只能在方法体内使用此形参,但不能进行重新赋值。*           *  static final 用来修饰属性:全局常量*/
public class FinalTest {final int WIDTH = 0;final int LEFT;final int RIGHT;
//  final int DOWN;{LEFT = 1;}public FinalTest(){RIGHT = 2;}public FinalTest(int n){RIGHT = n;}//    public void setDown(int down){//      this.DOWN = down;
//  }public void doWidth(){//      width = 20;}public void show(){final int NUM = 10;//常量
//      NUM += 20;}public void show(final int num){//      num = 20;//编译不通过System.out.println(num);}public static void main(String[] args) {int num = 10;        num = num + 5;        FinalTest test = new FinalTest();
//      test.setDown(3);    test.show(10);}
}final class FinalA{
}//class B extends FinalA{//
//}//class C extends String{//
//}class AA{public final void show(){       }
}class BB extends AA{// public void show(){//
//  }
}

335.面向对象(下)-final修饰属性
336.面向对象(下)-final修饰局部变量

337.面向对象(下)-final课后练习

1.排错

public class Something {public int addOne(final int x) {  return ++x;// return x + 1;}
}

++x对(final int x)进行了重新赋值,编译过不了
return x + 1可以,返回X+1之后的数,但是X没变

2.排错

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

o.i++;正确,o是常量没有改变,i可以改变,对象还是o,里面的i改变
打开// o = new Other();错误,改变了

338.面向对象(下)-每天一考

1.static 修饰的属性,相较于实例变量,有哪些特别之处(>=3点)

随着类的加载而加载;早于对象的创建;只要权限允许,可以通过”对象.static属性”的方式进行调用;存在于方法区的静态域

2.final 可以用来修饰哪些结构,分别表示什么意思

3.代码实现单例模式的饿汉式

4.代码实现单例模式的懒汉式 -目前还是线程不安全的。

5.类的属性赋值的位置有哪些?先后顺序为何?

默认初始化
显式初始化 、代码块中初始化
构造器中初始化
通过”对象.属性” 或”对象.方法”的方式赋值

339.面向对象(下)-复习:static
340.面向对象(下)-复习:单例模式
341.面向对象(下)-复习:main()
342.面向对象(下)-复习:代码块和final

抽象类和抽象方法

343.面向对象(下)-抽象类与抽象方法的使用

随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。

  • 用abstract关键字来修饰一个类,这个类叫做抽象类
  • 用abstract来修饰一个方法,该方法叫做抽象方法
    抽象方法:只有方法的声明,没有方法的实现。以分号结束:
    比如:public abstract void talk();
  • 含有抽象方法的类必须被声明为抽象类。
  • 抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重 写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍 为抽象类。
  • 不能用abstract修饰变量、代码块、构造器
  • 不能用abstract修饰私有方法、静态方法、final的方法、final的类
package com.atguigu.java;
/** abstract关键字的使用* 1.abstract:抽象的* 2.abstract可以用来修饰的结构:类、方法* * 3. abstract修饰类:抽象类*       > 此类不能实例化*      > 抽象类中一定有构造器,(自己不能new)便于子类实例化时调用(涉及:子类对象实例化的全过程)*      > 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作* * * 4. abstract修饰方法:抽象方法*      > 抽象方法只有方法的声明,没有方法体*      > 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。*      > 若子类重写了父类中的所有的抽象方法后,此子类方可实例化*        若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰*/
public class AbstractTest {public static void main(String[] args) {//一旦Person类抽象了,就不可实例化
//      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 void eat(){//
//  }//抽象方法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("学生多吃有营养的食物");}@Overridepublic void breath() {System.out.println("学生应该呼吸新鲜的没有雾霾的空气");}
}

344.面向对象(下)-抽象的应用场景


Java允许类设计者指定:超类声明一个方法但不提供实现,该方法的实现由子类提供。
这样的方法称为抽象方法。有一个或更多抽象方法的类称为抽象类
Vehicle是一个抽象类,有两个抽象方法。
注意:抽象类不能实例化,new Vihicle()是非法的

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( ) { //写出计算驳船行驶距离的具体方法}
}

345.面向对象(下)-abstract使用中的注意点

abstract使用上的注意点:
1.abstract不能用来修饰:属性、构造器等结构
2.abstract不能用来修饰私有方法、静态方法、final的方法、final的类

346.面向对象(下)-抽象类的练习:基本操作

347.面向对象(下)-创建抽象类的匿名子类对象

package com.atguigu.java;
//抽象类的匿名子类
public class PersonTest {public static void main(String[] args) {method(new Student());//匿名对象Worker worker = new Worker();method1(worker);//非匿名的类非匿名的对象method1(new Worker());//非匿名的类匿名的对象System.out.println("********************");//创建了一匿名子类的对象:pPerson p = new Person(){@Overridepublic void eat() {System.out.println("吃东西");}@Overridepublic void breath() {System.out.println("好好呼吸");}          };method1(p);System.out.println("********************");//创建匿名子类的匿名对象method1(new Person(){@Overridepublic void eat() {System.out.println("吃好吃东西");}@Overridepublic void breath() {System.out.println("好好呼吸新鲜空气");}});}public static void method1(Person p){p.eat();p.breath();}public static void method(Student s){        }
}class Worker extends Person{@Overridepublic void eat() {}@Overridepublic void breath() {}
}

348.面向对象(下)-模板方法的设计模式及应用场景

多态的应用:模板方法设计模式(TemplateMethod)
抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

解决的问题:
1.当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
2.换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用, 这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。

模板方法设计模式是编程中经常用得到的模式。各个框架、类库中都有他的 影子,比如常见的有:
数据库访问的封装
Junit单元测试
JavaWeb的Servlet中关于doGet/doPost方法调用
Hibernate中模板程序
Spring中JDBCTemlate、HibernateTemplate等

package com.atguigu.java;
//抽象类的应用:模板方法的设计模式
public class TemplateTest {public static void main(String[] args) {     SubTemplate t = new SubTemplate();     t.spendTime();}
}abstract class Template{//计算某段代码执行所需要花费的时间public void spendTime(){long start = System.currentTimeMillis();this.code();//不确定的部分、易变的部分long end = System.currentTimeMillis();System.out.println("花费的时间为:" + (end - start));}public abstract void code();
}class SubTemplate extends Template{@Overridepublic 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);}}}
}

349.面向对象(下)-抽象类的课后练习

接口

350.面向对象(下)-接口的理解

一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方 法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。

另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又 没有is-a的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打 印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都 支持USB连接。

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要…则 必须能…”的思想。继承是一个"是不是"的关系,而接口实现则是 "能不能" 的关系。

接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都要遵守。

351.面向对象(下)-接口的定义与使用

接口(interface)是抽象方法常量值定义的集合。

接口的特点:
用interface来定义。
接口中的所有成员变量都默认是由public static final修饰的。
接口中的所有抽象方法都默认是由public abstract修饰的。
接口中没有构造器
接口采用多继承机制。

package com.atguigu.java1;
/** 接口的使用* 1.接口使用interface来定义* 2.Java中,接口和类是并列的两个结构* 3.如何定义接口:定义接口中的成员*       *       3.1 JDK7及以前:只能定义全局常量和抽象方法*           >全局常量:public static final的.但是书写时,可以省略不写*           >抽象方法:public abstract的*           *       3.2 JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法(略)* * 4. 接口中不能定义构造器的!意味着接口不可以实例化* * 5. Java开发中,接口通过让类去实现(implements)的方式来使用.*    如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化*    如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类*    * 6. Java类可以实现多个接口   --->弥补了Java单继承性的局限性*   格式:class AA extends BB implements CC,DD,EE*   * 7. 接口与接口之间可以继承,而且可以多继承* * ******************************** 8. 接口的具体使用,体现多态性* 9. 接口,实际上可以看做是一种规范* * 面试题:抽象类与接口有哪些异同?* */
public class InterfaceTest {public static void main(String[] args) {System.out.println(Flyable.MAX_SPEED);System.out.println(Flyable.MIN_SPEED);
//      Flyable.MIN_SPEED = 2;Plane plane = new Plane();plane.fly();}
}//定义可以飞接口
interface Flyable{//全局常量public static final int MAX_SPEED = 7900;//第一宇宙速度int MIN_SPEED = 1;//省略了public static final//抽象方法public abstract void fly();//省略了public abstractvoid stop();//Interfaces cannot have constructors
//  public Flyable(){//
//  }
}interface Attackable{  void attack();
}//实现可以飞接口
class Plane implements Flyable{// 如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
//如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类@Overridepublic void fly() {System.out.println("通过引擎起飞");}@Overridepublic void stop() {System.out.println("驾驶员减速停止");}
}abstract class Kite implements Flyable{@Overridepublic void fly() {       }
}//先继承父类,后面实现接口
//实现了Flyable,Attackable,CC接口
class Bullet extends Object implements Flyable,Attackable,CC{@Overridepublic void attack() {// TODO Auto-generated method stub     }@Overridepublic void fly() {// TODO Auto-generated method stub        }@Overridepublic void stop() {// TODO Auto-generated method stub       }@Overridepublic void method1() {// TODO Auto-generated method stub        }@Overridepublic void method2() {// TODO Auto-generated method stub        }}
//************************************interface AA{void method1();
}
interface BB{   void method2();
}
//接口和接口之间可以继承
interface CC extends AA,BB{}

352.面向对象(下)-接口的多实现与接口的继承性

353.面向对象(下)-实例演示接口是一种规范

  • 定义Java类的语法格式:先写extends,后写implements
    class SubClass extends SuperClass implements InterfaceA{ }
  • 一个类可以实现多个接口,接口也可以继承其它接口。
  • 实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化。否则,仍为抽象类。
  • 接口的主要用途就是被实现类实现。(面向接口编程)
  • 与继承关系类似,接口与实现类之间存在多态性
  • 接口和类是并列关系,或者可以理解为一种特殊的类。从本质上讲, 接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义 (JDK7.0及之前),而没有变量和方法的实现。

354.面向对象(下)-创建接口匿名实现类对象

355.面向对象(下)-接口应用:代理模式

代理模式是Java开发中使用较多的一种设计模式。
代理设计就是为其他对象提供一种代理以控制对这个对象的访问。

代理类似中介的身份

应用场景
安全代理:屏蔽对真实角色的直接访问。
远程代理:通过代理类处理远程方法调用(RMI)
延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象
比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有 100MB,在打开文件时,不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用proxy来进行大图片的打开。

分类
静态代理(静态定义代理类):专门针对某个接口
动态代理(动态生成代理类):JDK自带的动态代理,需要反射等知识

package com.atguigu.java1;//接口的应用:代理模式
public class NetWorkTest {public static void main(String[] args) {//new一个真实的被代理类serverServer server = new Server();
//      server.browse();//相当于server赋予了ProxyServer中的NetWorkProxyServer proxyServer = new ProxyServer(server);proxyServer.browse();      }
}//代理类和被代理类共同实现的接口NetWork
interface NetWork{  public void browse();
}//被代理类
class Server implements NetWork{@Overridepublic void browse() {System.out.println("真实的服务器访问网络");}
}//代理类
class ProxyServer implements NetWork{//声明变量private NetWork work;//重提供当前代理类的构造器public ProxyServer(NetWork work){this.work = work;//对work进行初始化}public void check(){System.out.println("联网之前的检查工作");}@Overridepublic void browse() {check();//先调用check方法校验work.browse();//真实的情况下使用work进行browse操作}
}

356.面向对象(下)-接口应用:工厂模式

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

核心本质:
实例化对象,用工厂方法代替 new 操作。
将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。

工厂模式的分类
简单工厂模式:用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)
工厂方法模式:用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

357.面向对象(下)-接口课后两道笔试题

package com.atguigu.java1;interface A {int x = 0;
}class B {int x = 1;
}class C extends B implements A {public void pX() {//编译不通过。因为x是不明确的// System.out.println(x);System.out.println(super.x);//1System.out.println(A.x);//0      }public static void main(String[] args) {new C().pX();}
}

358.面向对象(下)-接口练习:比较对象大小

359.面向对象(下)-Java8中接口的新特性

Java 8中,你可以为接口添加静态方法和默认方法。从技术角度来说,这是完 全合法的,只是它看起来违反了接口作为一个抽象定义的理念。

静态方法:使用 static 关键字修饰。可以通过接口直接调用静态方法,并执行 其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中找到像Collection/Collections或者Path/Paths这样成对的接口和类。

默认方法:默认方法使用 default 关键字修饰。可以通过实现类对象来调用。 我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。 比如:java 8 API中对Collection、List、Comparator等接口提供了丰富的默认方法。

接口中的默认方法
若一个接口中定义了一个默认方法,而另外一个接口中也定义了一个同名同 参数的方法(不管此方法是否是默认方法),在实现类同时实现了这两个接 口时,会出现:接口冲突
解决办法:实现类必须覆盖接口中同名同参数的方法,来解决冲突。

若一个接口中定义了一个默认方法,而父类中也定义了一个同名同参数的非 抽象方法,则不会出现冲突问题。因为此时遵守:类优先原则。接口中具有 相同名称和参数的默认方法会被忽略。

360.面向对象(下)-Java8接口新特性的应用

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 {@Overridepublic void help() {System.out.println("我该就谁呢?");Filial.super.help();Spoony.super.help();}
}

361.面向对象(下)-内部类的分类

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。

在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类

Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
Inner class的名字不能与包含它的外部类类名相同

分类:
成员内部类(static成员内部类和非static成员内部类)
局部内部类(不谈修饰符)、匿名内部类

package com.atguigu.java2;
/** 类的内部成员之五:内部类* 1. Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类* * 2.内部类的分类:成员内部类(静态、非静态)  vs 局部内部类(方法内、代码块内、构造器内)* * 3.成员内部类:*        一方面,作为外部类的成员:*            >调用外部类的结构*           >可以被static修饰*            >可以被4种不同的权限修饰* *         另一方面,作为一个类:*          > 类内可以定义属性、方法、构造器等*          > 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承*            > 可以被abstract修饰* * * 4.关注如下的3个问题*   4.1 如何实例化成员内部类的对象*   4.2 如何在成员内部类中区分调用外部类的结构*   4.3 开发中局部内部类的使用  见《InnerClassTest1.java》 */
public class InnerClassTest {public static void main(String[] args) {//创建Dog实例(静态的成员内部类):Person.Dog dog = new Person.Dog();dog.show();//创建Bird实例(非静态的成员内部类):
//      Person.Bird bird = new Person.Bird();//错误的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("卡拉是条狗");
//          eat();}}//非静态成员内部类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{          }}
}

362.面向对象(下)-成员内部类的特点

成员内部类作为类的成员的角色:
1.和外部类不同,Inner class还可以声明为privateprotected
2.可以调用外部类的结构
3.Inner class 可以声明为static的,但此时就不能再使用外层类的非static的成员变量;

成员内部类作为类的角色:
1.可以在内部定义属性、方法、构造器等结构
2.可以声明为abstract类 ,因此可以被其它的内部类继承
3.可以声明为final
4.编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)

注意

  1. 非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员
  2. 内部类中才可声明static成员。
  3. 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式
  4. 成员内部类可以直接使用外部类的所有成员,包括私有的数据
  5. 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的

363.面向对象(下)-如何实例化成员内部类
364.面向对象(下)-成员内部类中调用外部类的结构

365.面向对象(下)-局部内部类的使用

package com.atguigu.java2;public class InnerClassTest1 {//开发中很少见public void method(){//局部内部类class AA{}}//返回一个实现了Comparable接口的类的对象public Comparable getComparable(){//创建一个实现了Comparable接口的类:局部内部类//方式一:
//      class MyComparable implements Comparable{//
//          @Override
//          public int compareTo(Object o) {//              return 0;
//          }
//
//      }
//
//      return new MyComparable();//方式二:return new Comparable(){@Overridepublic int compareTo(Object o) {return 0;}         };      }
}

【JavaSE】面向对象(下)(311~365)相关推荐

  1. Day06 JavaSE面向对象OOP(上) (Object-Oriented Programming)

    JavaSE 面向对象OOP(上) 一.面向对象概述 1 面向过程&面向对象区别 面向过程 第一步做什么,第二步做什么- 面向过程适合处理一些简单的问题. 面向对象 分类的思维模式,首先分类, ...

  2. 对象属性结构赋值_(六)面向对象-下

    (六)面向对象-下 关键字:static static 可以用来修饰的结构:主要用来修饰类的内部结构 属性.方法.代码块.内部类 static修饰属性:静态变量(类变量 属性,是否使用static修饰 ...

  3. JavaSE---05面向对象(下)

    05 面向对象(下) 5.1 关键字:static 5.1.1 概念及使用 概念 1.static:静态的. 2.static 可以用来修饰:属性.方法.代码块.内部类.3.使用 static 修饰属 ...

  4. Java全栈(二)JavaSE:14.面向对象下

    一.抽象类 1.1 由来 抽象:即不具体.或无法具体 例如:当我们声明一个几何图形类:圆.矩形.三角形类等,发现这些类都有共同特征:求面积.求周长.获取图形详细信息.那么这些共同特征应该抽取到一个公共 ...

  5. 面向对象下 abstract关键字(宋红康JAVASE)

    abstract关键字的使用 1 abstract:抽象的 2 abstract可以用来修饰的结构:类.方法 3 abstract修饰类:抽象类 此类不能实例化 抽象类中一定有构造器,便于子类实例化时 ...

  6. JavaSE面向对象编程

    面向对象 Java 使用面向对象编程(Object-Oriented Programming,OOP),这是一种编程风格,它旨在使思考编程更接近思考现实世界. java 中的对象 在面向对象中,每个对 ...

  7. 【JavaSE进阶(下)】自学笔记 记得收藏时时回顾

    集合 集合概述 1.什么是集合?有什么用? 数组其实就是一个集合.集合实际上就是一个容器,可以来容纳其他类型的数据. 集合为什么说在开发中使用较多? 集合是一个容器,是一个载体,可以一次容纳多个对象. ...

  8. JavaSE面向对象学习笔记总结

    1,构造函数: 用于给对象进行初始化,是给与之对应的对象进行初始化,它具有正对性,函数中的一种. 特点: 1. 该函数的名称和所在的类的名称相同 2. 不需要定义返回类型 3. 该函数没有具体的返回值 ...

  9. JavaSE——面向对象高级(继承、final关键字、抽象类与接口、多态、Object类、内部类、包装类、可变参数)

    第3节 面向对象高级 一.继承 1.1 概述和使用 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类.继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法 ...

最新文章

  1. vfp中,函数subs(计算机管理信息系统,7)返回的结果是,VFP选择题库(可发学生).xls...
  2. 动态新增元素的js无效的解决方法
  3. 构造函数中调用构造函数new和delete使用小结
  4. 高并发之--Guava Cache
  5. jdk1.8以前不建议使用其自带的Base64来加解密
  6. 【招聘(南京)】南京纳龙科技有限公司招高级.net开发工程师
  7. jedis与redis_Redis与Jedis排序
  8. 浅谈iptables防SYN Flood攻击和CC攻击
  9. Spring Boot (八)MyBatis + Docker + MongoDB 4.x
  10. oracle 实现HA,使用KeepAlived实现HAProxy高可用
  11. Oracle的学习一:安装与卸载、sql *plus常用命令、Oracle用户管理
  12. [leetcode] 65. 有效数字
  13. DTCC 年度最佳创新产品丨真正的 HTAP 数据库是怎样炼成的?
  14. win10相机打不开,显示错误代码0xA00F4246(0x800706D9)
  15. Windows系统与Linux系统下的硬盘分区操作
  16. c++string 加引号_C++|引用计数与shared_ptr智能指针(以实现String类为例)
  17. Elastic:运用 Elastic Maps 实时跟踪,可视化资产分布及地理围栏告警(一)
  18. 计算机在生物工程的应用,计算机在化学化工及生物工程中的应用
  19. 观点丨区块链未来这一年
  20. MFC com控件类

热门文章

  1. Node.js中使用moment
  2. 【CentOS7安装RabbitMQ及常用命令】
  3. 应用案例: ENVI图像处理软件和ArcGIS®在灾害救援工作中的应用
  4. Qt开发之路——整型与字符串 int与QString互转
  5. 商业模式新生代_商业模式设计方法:讲故事——《商业模式新生代》笔记之十一...
  6. ADS系列 - RLC器件滤波器设计教程1
  7. 代码随想录算法训练营第十三天|102.二叉树的层序遍历、226.翻转二叉树、101.对称二叉树
  8. python的=赋值的是地址
  9. 深圳大学计算机科学与技术考研报录比,深圳大学公布2020年最新考研报录比!近2.3万人报考,整体报录比达5:1...
  10. python开发对电脑配置要求_学python最电脑配置有要求么