子类对象的实例化过程:
我们可以用一个类的变量记住它的子类的子类的实例.这时如果调用子类中的方法,只需要强制转换子类就可以
没必要非得强制转换子类的子类.
instanceof关键字:也可以判断子类实例也属于父类的类型
/*
子类对象的实例化过程
我们可以用一个类的变量记住它的子类的子类的实例.这时如果调用子类中的方法,只需要强制转换子类就可以
没必要非得强制转换子类的子类.
instanceof关键字:也可以判断子类实例也属于父类的类型.
*/
class A
{
A()
{
//如果程序没有写构造方法的/java会默认给它添加构造方法!
}
public void a()
{
System.out.println("a() in A");
}
}
class B extends A
{
B()
{
super(); //默认调用父类的无参的构造方法!
}
public void a()
{
System.out.println("a()in B");
}
public void b()
{
System.out.println("b()in B");
}
}
class C extends B
{
public void a()
{
System.out.println("a()in C");
}
public void b()
{
System.out.println("b()in C");
}
public void c()
{
System.out.println("C()int C");
}
}
class Demo
{
public static void main(String[] args)
{
A a = new C();
if(a instanceof C)
{
C c =(C)a;
c.c();
}
if(a instanceof B)
{
B b = (B)a;
b.b();
}
}
}
继承的细节:\
1.子类不会继承与父类的私有的成员
2.构造函数是不会被继承.
3.只支持单继承,可以多重继承.
/*
继承的细节
.子类不会继承与父类的私有的成员
.构造函数是不会被继承.
.只支持单继承,可以多重继承.
------------------
.以后在设计一个类的时候,父类一定要加上一个不带参数的super,否则子类实例化的时候会报错!
为什么有这样一个机制:
解答:别人来继承与这样一个类,一定也需要这个子类具有父类的方法.但是别人并不知道在构造函数里面做了一些特别才能实现这个
的功能.所以java就规定子类实例化的过程中.一定会默认调用与父类的super()的构造方法.如果你在父类中没有定义一个无参的.
那么在实例化的过程中是会容易出错的.
*/
class Person
{
private String name ;
public Person(String name)
{
this.name = name;
}
public Person()
{
//咱们加一个无参的构造方法!
}
public void eat()
{
System.out.println("是人都要吃东西!");
}
}
class Student extends Person
{
public Student()
{
//不带参数的构造函数!
super(); //默认为这个? 但是有这个父类的构造函数吗?显然没有对吧.。
}
public void eat()
{
System.out.println("抽一根");
super.eat();
}
}
class Demo
{
public static void main(String[] args)
{
Student st = new Student();
st.eat();
}
}
第三:
/*
子类的实例化过程:子类在创建做了什么事情呢?
解答:在创建子类的时候,会调用子类的构造函数,在子类构造函数的第一行会默认调用父类的构造函数
在子类构造函数中如果没有显式地调用父类的构造函数.它会自动的调用父类的无参的构造函数(在这个问题上你要注意)
我们可以在构造函数中使用this(实参)来调用自己的带参数的构造方法
还可以用super(实参)去调用父类型的带了参数的构造方法/
但要注意:this 与super()只能出现一次. 并且在第一行.
如果一个构造函数调用了this ,那么就不能从第二个语句使用super()
*/
class Person
{
private String name ;
public Person()
{
System.out.println("无参的Person()被调用啦!");
}
public Person(String name )
{
this();
System.out.println("有参的Person()被调用啦!");
this.name = name;
}
}
class Student extends Person
{
private String name;
public Student()
{
super("kudy");
System.out.println("无参的Student()被调用啦~");
}
public Student(String name)
{
this(); //与super()不能同时出现
System.out.println("有参的Student()被调用啦~");
}
}
class Demo
{
public static void main(String[] args)
{
new Student("abc");
}
}
/*
输出的结构为:
--------------------------------
无参的Person()被调用啦!
有参的Person()被调用啦!
无参的Student()被调用啦~
有参的Student()被调用啦~
*/
第四:多态
/*
关于多态:
不变应万变
*/
abstract class Person
{
public abstract void eat();
}
class Chinese extends Person
{
public void eat()
{
System.out.println("中国的人还是广东人最好啦!");
}
}
class Shop
{
public void shopping(Person p )
{
System.out.println("咱们去买好东西吃!");
p.eat();
}
}
class Demo
{
public static void main(String[] args)
{
Shop shop = new Shop();
shop.shopping(new Chinese());
}
}
第五:面试题
/*
子类实例化的面试题!
A1 B2 B1
*/
class A
{
String name = "张三";
public A()
{
System.out.println("A1"); //A1
}
public A(String name)
{
this();
System.out.println("A2");
}
}
class B extends A
{
String name = "王五";
public B()
{
this("张"); //如果有了this 就是默认没了super()
System.out.println("B1");
}
public B(String name)
{
// super();
System.out.println("B2"); //B2
}
}
class Demo
{
public static void main(String[] args)
{
new B();
}
}
第六:再讲多态
/*
覆盖父类的方法:
子类当中覆盖父类的方法必须要和父类具有相同的方法名,具有相同的参数类型,具有相同的返回值 返回值类型一定要和
子类的保持一直.这样就是方法的重写
子类的方法的权限不能比父类有更严格的访问权限,因为我们经常要把子类当做父类来使用.
子类去访问父类的方法时,会比较一下子类的访问权限.如果权限比父类小.那么就挂啦
多态: 把子类当做父类来使用,针对父类进行方法的调用.传入不同的子类.执行的结构是一样的.
除非父类被子类这个哥们重写啦方法~
*/
class Person
{
public void run()
{
System.out.println("run() in Person");
}
public Person getInstance()
{
return new Person();
}
}
class Student extends Person
{
public void run()
{
System.out.println("happy");
super.run(); //调用了父类的run方法!
}
public Student getInstance() //权限不应该比父类的要小. 如果权限要比父类的小.那么就OH.Sorry
{
return new Student();
}
}
class Demo
{
public static void main(String[] args)
{
Student stu = new Student();
stu.run();
run(stu);
}
//实现了多态!
public static void run(Person p )
{
p = p.getInstance();
p.run(); //实现了多态
}
}
第七:final的应用:
/*
final 关键字:最终的!终态的
.被fina修饰的属性为常量,是不能被更改的.也就是说:值是不能被改变
.final所修饰的方法不能被重写,也就是说不能被子类所覆盖
.final修饰所修饰的类是不能被继承的!
一般fina的用法:public static fina String NAME = "kudy";
为什么它一般是和static一起的呢?
解答:
既然一个属性都不能被修改啦.是一个常量啦.咱们可以把他定义一个static的.在类出生的时候.它也会跟着出生.
方便.
*/
/*
final class Person
{
//被final所修饰的类是不能被继承的!
}
*/
class Person
{
public static final int NUM = 19 ;//给我修饰的常量是不能被修改的!
public final void show()
{
System.out.println("给我修饰的方法都是不能被重写!");
}
}
class Student extends Person
{
/*
public void show()
{
System.out.println("真的是不能被重写噢!");
}
*/
public void run (int num)
{
//先比较后自加!
System.out.println(++num);
System.out.println(num++);
//? 为多少呢? 20 //因为第一次自加1 后来第二次的时候。先输出值它自己再加1
}
}
class Demo
{
public static void main(String[] args)
{
Student stu = new Student();
stu.run(stu.NUM);
}
}
设计模式:
组合
/*
设计模式!组合
组合:当一个对象在运作的过程中必须要用到另外一个对象的时候,然而又不是构成继承的关系的!
*/
class Guo
{
public void heat()
{
System.out.println("已经自动的加热啦~");
}
}
class Chef
{
//吃食品的时候一定要把它加热嘛~~
Guo guo;
Chef(Guo guo)
{
this.guo = guo;
}
public void cook()
{
guo.heat();
}
}
class Demo
{
public static void main(String[] args)
{
Chef chef = new Chef(new Guo());
chef.cook();
}
}
抽象类的简单使用:
/*
抽象类:
.没有方法体必须要声明为abstract抽象方法
.含有抽象方法的类一定是抽象类
.抽象类的定义:用abstract修饰的类叫做抽象类
.抽象类是不能被实例化的(也就是说不能创建对象!);
.可以用一个抽象类来继承一个抽象类.会继承所有的方法
.如果用一个类来继承抽象类,那么必须要实现抽象类里面所有的方法
.抽象类的访问权限没有什么特殊之处.主要是看修饰符!
.抽象类里面不一定有抽象方法.但是包含有抽象方法一定是抽象类
*/
abstract class A
{
abstract void a();//抽象方法!
public void run()
{
System.out.println("A run()");
}
}
abstract class B extends A
{
abstract void b();
}
class C extends B
{
//必须要把它所继承的所有的抽象方法实现!
public void a()
{
System.out.println("A.class");
}
public void b()
{
System.out.println("B.class"); //实现B
}
}
class Demo
{
public static void main(String[] args)
{
A a = new C();
if(a instanceof C)
{
C c = (C)a;
c.a();
c.b();
c.run();
}
}
}
模板方法的设计模式:
/*
模板方法的设计模式:
定义一个抽象类作为模板,将具体做事情方法定义出来,但是不实现
.对外提供一个共有的方法作为接口,规定做事情的顺序/这个方法应该为final 避免了让子类重写
子类继承模板,实现所有的抽象方法()
*/
abstract class AbatractPrint
{
abstract void opend();
abstract void print();
abstract void close();
//定义成终态的.避免了子类所修改!
public final void run()
{
this.opend();
print();
close(); //调用方法!
}
}
class StringPrint extends AbatractPrint
{
private String data;
StringPrint(String data)
{
this.data = data;
}
public void opend()
{
System.out.print("<<");
}
public void print()
{
System.out.print(data);
}
public void close()
{
System.out.print(">>");
}
}
class Demo
{
public static void main(String[] args)
{
AbatractPrint abatractPrint = new StringPrint("kudy");
abatractPrint.run();
//使用匿名内部类做一下这道题目!
//我现在不是为了抽象类创建对象.而是为了匿名子类! //也多多态的一种形式!
//匿名内部类重写了父类的方法!并且调用一把run();
new AbatractPrint(){
public void opend()
{
System.out.print("<<");
}
public void print()
{
System.out.print("show");
}
public void close()
{
System.out.print(">>");
}
}.run();
}
}
面向对象的例子:
//定义抽象类作为接口,实现个模块之间的解耦
/*
首先第一种方法的: 显示就是三个人不能同时分工协作啦~~
咱们传入的时候要注意: 我们传入的是子类. 父类型的引用指向了子类型的对象。
*/
//定义一个抽象的数据产生器!
import java.io.*;
abstract class Generator
{
abstract String getData();
}
//定义一个抽象的数据处理器
abstract class DataHandler
{
abstract String handleData(Generator generator);
}
//甲负责写数据产生器
class OneGenerator extends Generator
{
public String getData()
{
return "hello"; //产生了一个数据!
}
}
//乙所负责写的数据处理代码
class OneDataHandler extends DataHandler
{
public String handleData(Generator generator)
{
String data = generator.getData();
return "~~"+data+"~~";
}
}
//数据产生器!
class TwoGenerator extends Generator
{
public String getData()
{
return "小细加油";
}
}
//数据处理器!
class TwoDataHandler extends DataHandler
{
public String handleData(Generator generator)
{
String data = generator.getData();
return "~~~"+data+"~~~";
}
}
/*
数据显示!
*/
class Demo
{
public static void main(String[] args) throws Exception
{
BufferedReader br
= new BufferedReader(new InputStreamReader(System.in));
/*
DataHandler data = new OneDataHandler();
Generator gen = new OneGenerator();
*/
//通过读取键盘获得用户使用的数据产生器名字
System.out.println("请输入您使用的数据产生器:");
String generatorClassName = br.readLine();
//根据类名反射出类
//Class class -->new Class()对象 --》class.Class
//1-1根据类名反射出类!
Class generatorClazz = Class.forName(generatorClassName); //类
//又因为返回的是object 类型/所以我们要强制转换.否则没有办法赋值。
//根据类创建实例对象(数据产生器)
Generator generator=( Generator) generatorClazz.newInstance(); //类创建对象。并且是父类型的引用指向子类型的对象。
//2.通过反射获得数据的处理器对象
System.out.println("请输入您要使用的数据处理器:");
String dataHandlerClassName = br.readLine();
Class dataHandlerClazz = Class.forName(dataHandlerClassName);
DataHandler dataHandler = (DataHandler)dataHandlerClazz.newInstance();
String data = dataHandler.handleData(generator);
System.out.println(data);
}
}