JAVA中 final object abstract 接口 多态 内部类

final object abstract 接口 多态 内部类

final  是一个关键字,是最后的,最终的,被修饰的内容不能改变

可以修饰的内容:

1. 类:final修饰的类不能有子类.

2. 成员变量:变量是一个终值,不能再被改变.所以在定义时必须先手动给一个值.

3. 局部变量:被final修饰的局部变量是一个终值,不能再被改变.

4. 方法:final修饰的方法不允许重写

- final修饰变量的时候必须初始化

空白final,数据类型是可以不赋初始值,可以在创建对象的调用构造方法的时候,赋初始值

如果final成员变量 定义时不给值,但是在构造方法里必须给值

如果成员变量在定义时先不给值,但是必须在构造方法中给值,即必须保证属性是被初始化了的.这种情况叫空白final.

空白final:指被声明为final但又未给定初值的域.但是无论什么情况,编译器都确保空白final在使用前必须被初始化.

好处:空白final在final的使用上提供了更大的灵活性,因为一个类中的final域可以做到根据对象而有所不同,却又保持其恒定不变的特性.

public class BlankFinal {

private final int i = 0;

private final int j;

private final Poppet p;

public BlankFinal() {

j = 1;

p = new Poppet();

}

public BlankFinal(int j) {

this.j = j;

p = new Poppet();

}

public static void main(String[] args) {

BlankFinal bf = new BlankFinal();

}

}

class Poppet {

}

- 什么情况下不能有子类?

1.类中功能已经很全了,String

抽象类 abstract

抽象类:在继承中,提取父类方法的时候,每个子类都有自己具体的方法实现,父类不能决定他们各自的实现方法所以父类干脆就不管了,在父类中只写方法的声明(负责制定一个规则),将方法的实现交给子类.在类中只有方法声明的方法叫抽象方法,拥有抽象方法的类叫抽象类。

**抽象类的功能:**1.可以节省代码 2.可以制定一批规则。

抽象类不一定有抽象方法,但是有抽象方法的一定时抽象类

抽象类不能创建对象,必须通过非抽象类的子类,创建对象

继承了抽象类的子类一定要实现抽象方法,如果不实现就只能将自己也变成抽象的.

抽象方法,就是确定你必须做这件事,但是你做这件事的方法,得你自己定。比如:老师让做一道题,学生做的方法可以一样但是必须的做。

- abstract与 final 和 private static 不可共用。

-

1.final:被final修饰的类不能有子类,方法不能重写,但是abstract必须有子类,必须重写

2.static:修饰的方法可以通过类名调用,abstract必须通过子类实现

3.private:修饰的方法不能重写,abstract必须重写

接口 interface 声明规则

接口也是抽象的

- 成员变量默认:public final static

- 成员方法默认:public abstract

为什么要可以实现多个接口?

让java间接实现多继承,

- 接口和接口之间时多继承。

1. 问题一:接口与父类可以同时存在吗?  可以

2. 问题二:父类与接口的功能如何分配? 一般父类中放的时主要功能,接口中放的是额外的功能,接口作为父类的补充。

3. 问题三:接口和接口之间的关系? 接口和接口之间可以多继承

接口中子类重写方法注意:

- 如果以个类实现了两个接口,者两个接口同时出现的抽象方法,在这个子类中,只需重写一次这个方法。

- 如果接口中有default修饰的方法是不需要重写的。

interface inter6{

public void run();

default public void eat(){     //default只能放在接口中

System.out.println(“default1”);

static public void bark(){

System.out.println(“static1”);

}

public void play();

}

class Test6 implements inter5{

//

public void run() {

System.out.println(“Test6”);

}

- 如果两个接口中方法名相同都是default方法,里面的方法体不同,在类中需要重写该方法。

- 如果两个接口中方法名,参数都相同的方法,一个接口是抽象方法,另一个是default修饰有方法体。这时该类也必须重写该方法。

- 子类的静态方法可以与父类的相同,但是方法在调用的时候各自调用各自的

-

static public void bark(){

System.out.println(“substatic”);

}

如果两个接口有同样的方法,可以用一个类来实现。

从JDK1.7,以后的接口,但是方法必须使用Static或者default修饰,因为接口的方法必须重写,麻烦。如果两个接口有同样的已经实现的方法,必须重写

面向接口编程,一个类一个接口,使用的时候调接口。

设计模式:前人总结的经验,一些常见问题的解决方法,后人直接拿来用

常用的设计模式23:单例,工厂,代理,适配器,装饰,模板,观察者等,每个单例都有一个对应的类

第一种:单例:一个类只允许有一个对象,建立一个全局的访问点,提供出去供大家使用。

- 类中手动重写构造,并且私有化

- 在类的里面 new一个对象(private final static ),在方法public里提供访问,必须是静态的(因为不需要对象调用)

-

为什么要final修饰引用,引用不可变

注意:在单例中一般只有向外提供s的方法是静态的,其他的都是非静态的

1. 形式 饿汉式

public class Singleton {

// 将自身实例化对象设置为一个属性,并用static、final修饰

private static final Singleton instance = new Singleton();

// 构造方法私有化

private Singleton() {}

// 静态方法返回该实例

public static Singleton getInstance() {

return instance;

}

}

“饿汉模式”的优缺点:

优点:实现起来简单,没有多线程同步问题。

缺点:当类SingletonTest被加载的时候,会初始化static的instance,静态变量被创建并分配内存空间,从这以后,这个static的instance对象便一直占着这段内存(即便你还没有用到这个实例),当类被卸载时,静态变量被摧毁,并释放所占有的内存,因此在某些特定条件下会耗费内存。

2. 形式 懒汉式

public class Singleton {

// 将自身实例化对象设置为一个属性,并用static修饰

private static Singleton instance;

// 构造方法私有化

private Singleton() {}

// 静态方法返回该实例

public static Singleton getInstance() {

if(instance == null) {

instance = new Singleton();

}

return instance;

}

}

“懒汉模式”的优缺点:

优点:实现起来比较简单,当类SingletonTest被加载的时候,静态变量static的instance未被创建并分配内存空间,当getInstance方法第一次被调用时,初始化instance变量,并分配内存,因此在某些特定条件下会节约了内存。

缺点:在多线程环境中,这种实现方法是完全错误的,根本不能保证单例的状态。

通过地址的长期保存,来保存对象

- 使用: 功能从局部变成全局的。对象也变成全局。

高内聚低耦合:模块之间的联系越少越好。

模块化编程:

单例的例子:runtime

多态:一种事物的多种形态

- 继承是多态的前提

- 方法重写

- 父类引用指向子类对象,直接父类和间接父类都行

程序运行的阶段:

预编译:程序打开的时候,活儿已经干完了.(预处理命令 #define)

编译:从打开程序开始到点击左上角的三角之前—只能识别=前面的引用类型,不会识=后面的对象

运行:从点击三角开始—真正的识别对象,对象开始干活儿

实现动态的手段:动态类型,动态绑定,动态加载

**动态加载:**我们在编译阶段不能确定具体的对象类型,只有到了运行阶段才能确定真正的干活儿的对象.

**运行多态(Person p = new Student();)的工作机制:**在编译的时候识别的是引用类型,不识别对象.所以只能识别出Person里面的方法,但是在运行的时候是右边的对象去执行操作的。

缺点:只能直接调用子类重写父类的方法,不能直接调用子类特有的功能。(是因为编译的时候,执行的左边,如果引用去调用子类特有的方法时,机器识别不了,会报错)

优点:提高代码的扩展性,Demo9

向上转型和向下转型

注意:在多态环境下,才有向下转型和向上转型

- 向上转型:相当与是自动类型转换,多态本身就是向上转型,

- 作用:实现多态

- 向下转型:相当与强制类型转换

- 作用:解决多态中无法调用子类特有属性的缺点。

instanceof:确定当前对象是否是后面类或子类的对象,返回true or false。因为多态所以不知道,运行时,父类代表谁的对象。

insranceof 前后必须有继承关系!

多态下成员变量的使用

- 编译的时候能不能访问看父类,运行时也看父类。

- 静态成员方法:编译时运行时都看父类。

Object 基类

- equals();

- hashCode();

- toString(); 打印对象的时候默认调用toString();通过重写toString可以输出对象的属性;

- getClass();得到当前对象的字节码文件。Class 类,

在java世界里,一切皆对象。从某种意义上来说,java有两种对象:实例对象和Class对象。每个类的运行时的类型信息就是用Class对象表示的。它包含了与类有关的信息。其实我们的实例对象就通过Class对象来创建的。Java使用Class对象执行其RTTI(运行时类型识别,Run-Time Type Identification),多态是基于RTTI实现的。

每一个类都有一个Class对象,每当编译一个新类就产生一个Class对象,基本类型 (boolean, byte, char, short, int, long, float, and double)有Class对象,数组有Class对象,就连关键字void也有Class对象(void.class)。Class对象对应着java.lang.Class类,如果说类是对象抽象和集合的话,那么Class类就是对类的抽象和集合。

Class类没有公共的构造方法,Class对象是在类加载的时候由Java虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。

- clone();

内部类:定义在一个类中的类,内部类的地位和外部类的成员变量,成员方法一样。内部类可以直接访问外部类 包括私有的,成员之间是可以相互调用的。

调用内部类的方式:第一种:借助于外部类的方式实现  第二种:直接在这里调用(外部类.内部类)

1.Outer.Inner in=Outer.new Inner();   //创建内部类的对象

2.import导包,直接创建

作用:可以间接实现多继承。

class A1{

}

class B1{

}

//说明功能

//我们可以通过内部类让java间接实现多继承

class X extends A1{

class Y extends B1{

}

}

局部内部类:定义在方法中的类,生存周期和方法一样。

作用:可以让功能私有化,在类中。对方法内部的代码进行整理,增强代码可读性

class Test11{

public void play() {

//我们通过局部内部类实现了功能的私有化,并对方法内部的代码进行了整理,增强了代码的可读性和可操作性.

//因为函数的定义不能嵌套,所以这里要通过局部内部类实现

//        public void gongneng1(){

//            System.out.println(“功能1”);

//        }

//        public void gongneng2(){

//            System.out.println(“功能2”);

//        }

class Inner{

public void gongneng1(){

System.out.println(“功能1”);

}

public void gongneng2(){

System.out.println(“功能2”);

}

}

Inner inner = new Inner();

inner.gongneng1();

inner.gongneng2();

}

public void run(){

//因为两个方法是play的局部内部类方法.play之外不可见

//        gongneng1();

//        gongneng2();

}

}

局部内部类所在的方法中局部变量的使用

- 局部变量的作用域:定义变量开始到函数结束

- final:被final修饰的变量会被放在常量区,而常量区的值存在的时间要大于局部变量的所在的方法,相当于从原来的基础上扩大了作用域,

- **原理:**当方法中同时存在局部内部类与成员变量时,成员变量的使用范围就会从原来的基础上进行扩大.

原因 ::在当前的情况下,程序会默认让final去修饰height.所以当局部变量所在的方法结束的时候,变量没有被释放,保存的值还在.

public class Demo15 {

public static void main(String[] args) {

Outer1 outer1 = new Outer1();

outer1.show();

}

}

class Outer1{

int age;

public void show() {

int height=8;

//局部内部类

class Inner{

public void eat() {

System.out.println(“eat”+height);

}

}

System.out.println(“show”);

Inner inner = new Inner();

inner.eat();

}

}

在jdk1.7之后,java的内部机制已经在变量的前面默认添加了final

静态内部类:不一定有静态方法,有静态方法必须有静态内部类。

Out.Inn in = new Out.Inn(); / /创建

class Out{

static int age;

//静态内部类不一定有静态方法,有静态方法的一定是静态内部类

static class Inn{//静态内部类

public void play() {

System.out.println(“play”);

}

public static void show() {

System.out.println(“show”);

}

}

}

匿名内部类:定义在类方法中的匿名子类对象。

创建匿名内部类对象注意点:1.匿名内部类对象必须有父类或者父接口

所有的匿名对象,除了Object匿名对象,都是匿名内部类

* 内部类的作用:

* 1.间接实现了多继承

* 2.方便定义

* 3.只有外部类可以访问创建的内部类的属性和方法,包括私有方法

* 4.同一个包中其他的类不可见,有了很好的封装性

- new Animal11().eat();//匿名对象

- new Dog11().eat();   //匿名子对象:使用已有的子类创建匿名子类对象

- 第二种方式:这里也是Animal的匿名子类对象

new Animal11() {

@Override

public void eat() {

// TODO Auto-generated method stub

super.eat();

}

public void show() {

}

}.show();

匿名内部类

//匿名内部类:

class Test1{

public void show() {

//匿名内部类

new Animal() {

@Override

public void eat() {

// TODO Auto-generated method stub

super.eat();

}

};

}

//普通的匿名对象作为参数

public void canShuTest() {

System.out.println(new Animal());

}

//匿名内部类作为参数

public void canShuTest1() {

System.out.println(

new Animal() {

public void eat() {

// TODO Auto-generated method stub

super.eat();

}

@Override

public String toString() {

return “haha”;

}

}

);

}

//普通的匿名对象作为返回值

public Animal fanHuiZhiTest() {

return new Animal();

}

//匿名内部类作为返回值

public Animal fanHuiZhiTest1() {

return new Animal() {

};

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值