面向过程(POP)与面向对象(OOP):

面向对象: Object Oriented Programming

面向过程: Procedure Oriented Programming

二者都是一种思想,面向对象是相对于面向过程而言的。

面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。

面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则。

面向对象的三大特征:

封装 (Encapsulation)

继承 (Inheritance)

多态 (Polymorphism)

面向对象的思想概述:

类(Class)和对象(Object)是面向对象的核心概念。

类是对一类事物的描述,是抽象的、概念上的定义。

对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。

类的访问机制:

在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。

在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员。

注:static方法不可访问非static属性。

栈(Stack):

是指虚拟机栈。虚拟机栈用于存储局部变量等。

局部变量表存放了基本数据类型、对象引用。方法执行完,自动释放。

堆(Heap)

存放对象实例,所有的对象实例以及数组都要在堆上分配。

方法区(Method Area)

用于存储已被虚拟机加载的类信息、 常量、 静态变量、即时编译器编译后的代码等数据。

匿名对象:

可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象。如:new Person().shout();

垃圾回收:

垃圾回收机制只回收JVM堆内存里的对象空间。

可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收。

垃圾回收机制回收任何对象之前,总会先调用它的finalize方法

(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)。

永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。

成员变量(属性)和局部变量的区别?

成员变量:

成员变量定义在类中,在整个类中都可以被访问。

成员变量分为类成员变量和实例成员变量,实例变量存在于对象所在的堆内存中。

成员变量有默认初始化值。

成员变量的权限修饰符可以根据需要,选择任意一个

局部变量:

局部变量只定义在局部范围内,如:方法内,代码块内等。

局部变量存在于栈内存中。

作用的范围结束,变量空间会自动释放。

局部变量没有默认初始化值,每次必须显式初始化。

局部变量声明时不指定权限修饰符

局部变量没有修饰符,与所在的方法修饰符相同。

方法:

没有具体返回值的情况,如果使用return,仅可用来结束方法。

方法中只能调用方法或属性,不可以在方法内部定义方法。

方法的重载(overload) :

重载的概念:

在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。

重载的特点:

与返回值类型无关,只看参数列表,且参数列表必须不同 (参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。

可变个数的形参:

JavaSE5.0中提供了Varargs(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。

从而,可以用一种更简单的方式,来传递个数可变的实参。

说明:

  1. 声明格式: 方法名(参数的类型名 …参数名)
  2. 可变参数:方法参数部分指定类型的参数个数是可变多个: 0个, 1个或多个
  3. 可变个数形参的方法与同名的方法之间,彼此构成重载
  4. 可变参数方法的使用与方法参数部分使用数组是一致的(可变形参和数组不构成重载,报编译错误)
  5. 方法的参数部分有可变形参,需要放在形参声明的最后
  6. 在一个方法的形参位置,最多只能声明一个可变个数形参
int[] arr = new int[10];
System.out.println(arr);
//输出的是地址值,没有重写print方法

char[] arr1 = new char[10];
System.out.println(arr1);   
//输出不是地址值,因为print(char[])重写了print方法

递归方法:

一个方法体内调用它自身。

方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。

递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。

// 一个简单的递归
// 计算1-100之间所有自然数的和
public int sum(int num) {
	if (num == 1) {
		return 1;
	} else {
		return num + sum(num - 1);
	}
}

//计算打印的次数
public static void main(String[] args) {
	recursion(10);
}
private static int count = 0;
public static int recursion(int k){
	count++;
	System.out.println("count1:" + count + " k:" + k);
	if(k <= 0){
		return 0;
	}
	return recursion(k - 1) + recursion(k - 2);

封装性

高内聚,低耦合:

高内聚:类的内部数据操作细节自己完成,不允许外部干涉;

低耦合:仅对外暴露少量的方法用于使用。

隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。

目的:

隐藏一个类中不需要对外提供的实现细节;

使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;

便于修改,增强代码的可维护性;

当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。

这里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没其他制约条件。

但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件。

这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。

权限修饰符:

修饰符

类内部

同一个包

不同包的子类

同一个工程

private

Yes

(缺省)

Yes

Yes

protected

Yes

Yes

Yes

public

Yes

Yes

Yes

Yes

对于class的权限修饰只可以用public和default(缺省)。

public类可以在任意地方被访问。

default类只可以被同一个包内部的类访问

构造器:

构造器的特征

具有与类相同的名称

不声明返回值类型。(与声明为void不同)

不能被static、 final、 synchronized、 abstract、 native修饰,不能有return语句返回值。

构造器的作用:创建对象,给对象进行初始化。

Java语言中,每个类都至少有一个构造器,默认构造器的修饰符与所属类的修饰符一致,一旦显式定义了构造器,则系统不再提供默认构造器,一个类可以创建多个重载的构造器,父类的构造器不可被子类继承。

构造器之间可以构成重载:构造器重载,参数列表必须不同 。

JavaBean:

JavaBean是一种Java语言写成的可重用组件。

所谓javaBean,是指符合如下标准的Java类:

1、类是公共的

2、有一个无参的公共的构造器

3、有属性,且有对应的get、set方法

用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。

用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。

UML类图:

  1. +表示public类型,-表示private 类型,#表示protected类型
  2. 方法的写法:方法的类型(+、 -)方法名(参数名:参数类型):返回值类型

this关键字:

它在方法内部使用,即这个方法所属对象的引用;

它在构造器内部使用,表示该构造器正在初始化的对象。

this可以调用类的属性、方法和构造器 。

使用this访问属性和方法时,如果在本类中未找到,会从父类中查找

注意:

可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其他的构造器!

构造器中不能通过"this(形参列表)"的方式调用自身构造器,

如果一个类中声明了n个构造器,则最多有n - 1个构造器中使用了"this(形参列表)",

"this(形参列表)"必须声明在类的构造器的首行,

在类的一个构造器中,最多只能声明一个"this(形参列表)"。

MVC设计模式:

MVC是常用的设计模式之一,将整个程序分为三个层次:视图模型层,控制器层,与数据模型层。

这种将程序输入输出、数据处理,以及数据的展示分离开来的设计模式使程序结构变的灵活而且清晰,同时也描述了程序各个对象间的通信方式,降低了程序的耦合性。

模型层 model 主要处理数据

数据对象封装 model.bean/domain

数据库操作类 model.dao

数据库 model.db

控制层 controller 处理业务逻辑

应用界面相关 controller.activity

存放fragment controller.fragment

显示列表的适配器 controller.adapter

服务相关的 controller.service

抽取的基类 controller.base

视图层 view 显示数据

相关工具类 view.utils

自定义view view.ui

JDK中主要的包介绍:

  1. java.lang----包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能
  2. java.net----包含执行与网络相关的操作的类和接口。
  3. java.io ----包含能提供多种输入/输出功能的类。
  4. java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
  5. java.text----包含了一些java格式化相关的类
  6. java.sql----包含了java进行JDBC数据库编程的相关类/接口
  7. java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 B/S C/S

继承性(inheritance) :

为什么要有继承?

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

作用:

继承的出现减少了代码冗余,提高了代码的复用性。

继承的出现,更有利于功能的扩展。

继承的出现让类与类之间产生了关系,提供了多态的前提。

子类不能直接访问父类中私有的(private)的成员变量和方法。

方法的重写(override/overwrite):

定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。

在程序执行时,子类的方法将覆盖父类的方法。

要求:

  1. 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
  2. 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
  3. 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
  4. 子类方法抛出的异常不能大于父类被重写方法的异常
  5. 子类不能重写父类中声明为private权限的方法

注意:

子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。

因为static方法是属于类的,子类无法覆盖父类的static方法。

super关键字:

在Java类中使用super来调用父类中的指定操作:

super可用于访问父类中定义的属性

super可用于调用父类中定义的成员方法

super可用于在子类构造器中调用父类的构造器

注意:

当子父类出现同名成员时,可以用super表明调用的是父类中的成员,super的追溯不仅限于直接父类super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识

调用父类的构造器:

子类中所有的构造器默认都会访问父类中空参数的构造器,当父类中没有空参数的构造器时,子类的构造器必须通过this(参数列表)或者super(参数列表)语句指定调用本类或者父类中相应的构造器。

同时只能”二选一”,且必须放在构造器的首行如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错。

this和super的区别:

No.

区别点

this

super

1

访问属性

访问本类中的属性,如果本类没有此属性则从父类中继续查找

直接访问父类中的属性

2

调用方法

访问本类中的方法,如果本类没 有此方法则从父类中继续查找

直接访问父类中的方法

3

调用构造器

调用本类构造器,必须放在构造器的首行

调用父类构造器,必须放在子类构造器的首行

多态性:

对象的多态性:父类的引用指向子类的对象(向上转型(upcasting)),可以直接应用在抽象类和接口上。

Java引用变量有两个类型:编译时类型和运行时类型。

编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。

若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)。

一个变量只能有一种确定的数据类型

一个引用类型变量可能指向(引用)多种不同类型的对象

一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法。

虚拟方法调用(Virtual Method Invocation):

子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。

重载与重写:

重载,是指允许存在多个同名方法,而这些方法的参数不同。

编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。

它们的调用地址在编译期就绑定了。

Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。

所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;

而对于重写(多态),只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定” 。

instanceof 操作符:

x instanceof A:检验x是否为类A的对象,返回值为boolean型。

对象类型转换 (Casting ):

基本数据类型的Casting:

自动类型转换:小的数据类型可以自动转换成大的数据类型

强制类型转换:可以把大的数据类型强制转换(casting)成小的数据类型

对Java对象的强制类型转换称为造型:

从子类到父类的类型转换可以自动进行

从父类到子类的类型转换必须通过造型(强制类型转换)实现

无继承关系的引用类型间的转换是非法的

在造型前可以使用instanceof操作符测试一个对象的类型

子类继承父类:

若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。

对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量。

Object类中的主要结构:

NO.

方法名称

类型

描述

1

public Object()

构造

构造器

2

public boolean equals(Object obj)

普通

对象比较

3

public int hashCode()

普通

取得Hash码

4

public String toString()

普通

对象打印时调用

==与equals方法:

用“==”进行比较时, 符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错

//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
//保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在
//-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率
public class Test1 {
	public static void main(String[] args) {
		Integer i = new Integer(1);
		Integer j = new Integer(1);
		System.out.println(i == j);//false
		Integer m = 1;
		Integer n = 1;
		System.out.println(m == n);//true
		Integer x = 128;
		Integer y = 128;
		System.out.println(x == y);//false
	}
}

static关键字:

使用范围:在Java类中,可用static修饰属性、方法、代码块、内部类

被修饰后的成员具备以下特点:

随着类的加载而加载

优先于对象存在

修饰的成员,被所有对象所共享

访问权限允许时,可不创建对象,直接被类调用

在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。

因为不需要实例就可以访问static方法,因此static方法内部不能有this,也不能有super。

static修饰的方法不能被重写

import static 表示导入指定类的static的属性或方法

单例 (Singleton)设计模式 :

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

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为private,这样,就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。

单例模式的优点:

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

举例 java.lang.Runtime

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

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

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

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

main方法:

由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public,又因为Java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的,因为main()方法是静态的,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员 。

代码块:

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

代码块(或初始化块)的分类:

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

static代码块通常用于初始化static的属性

静态代码块:用static修饰的代码块

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

非静态代码块:没有static修饰的代码块

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

final关键字:

final标记的变量(成员变量或局部变量)即称为常量,且只能被赋值一次。

final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋值,然后才能使用。

static final:全局常量

抽象类:

含有抽象方法的类必须被声明为抽象类。

不能用abstract修饰变量、代码块、构造器;

不能用abstract修饰私有方法、静态方法、final的方法、final的类。

模板方法设计模式:

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

解决的问题:

当功能内部一部分实现是确定的,一部分实现是不确定的。

这时可以把不确定的部分暴露出去,让子类去实现。

换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。

但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。

模板方法设计模式是编程中经常用得到的模式。各个框架、类库中都有他的影子,比如常见的有:

数据库访问的封装

Junit单元测试

JavaWeb的Servlet中关于doGet/doPost方法调用

Hibernate中模板程序

Spring中JDBCTemlate、 HibernateTemplate等

接口:

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

接口的特点:

接口中的所有成员变量都默认是由public static final修饰的。

接口中的所有抽象方法都默认是由public abstract修饰的。

接口中没有构造器。

JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法。

查找:

线性查找:

实现思路:通过遍历的方式,一个一个的数据进行比较、查找。

适用性:具有普遍适用性。

二分法查找:

实现思路:每次比较中间值,折半的方式检索。

适用性:(前提:数组必须有序)

代理模式:

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

应用场景:

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

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

延迟加载: 先加载轻量级的代理对象,真正需要再加载真实对象。

工厂方法:

概述:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。

适用性:

  1. 当一个类不知道它所必须创建的对象的类的时候
  2. 当一个类希望由它的子类来指定它所创建的对象的时候
  3. 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候

FactoryMethod模式是设计模式中应用最为广泛的模式,在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要。

FactoryMethod解决的就是这个问题,它通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。

接口和抽象类之间的对比:

No.

区别点

抽象类

接口

1

定义

包含抽象方法的类

主要是抽象方法和全局常量的集合

2

组成

构造方法、抽象方法、普通方法、 常量、变量

常量、抽象方法、 (jdk8.0:默认方法、静态方法)

3

使用

子类继承抽象类(extends)

子类实现接口(implements)

4

关系

抽象类可以实现多个接口

接口不能继承抽象类,但允许继承多个接口

5

常见设计模式

模板方法

简单工厂、工厂方法、代理模式

6

对象

都通过对象的多态性产生实例化对象

7

局限

抽象类有单继承的局限

接口没有此局限

8

实际

作为一个模板

是作为一个标准或是表示一种能力

9

选择

如果抽象类和接口都可以使用的话,优先使用接口,因为避免单继承的局限

静态方法和默认方法:

Java8中,你可以为接口添加静态方法和默认方法。

静态方法:使用static关键字修饰。只能通过接口直接调用静态方法,并执行其方法体。

默认方法:默认方法使用default关键字修饰。可以通过实现类对象来调用。

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

解决办法:实现类必须覆盖接口中同名同参数的方法,来解决冲突。

若一个接口中定义了一个默认方法,而父类中也定义了一个同名同参数的非抽象方法,则不会出现冲突问题。

因为此时遵守:类优先原则。接口中具有相同名称和参数的默认方法会被忽略。

Java中的JUnit单元测试:

步骤:

1.中当前工程 - 右键择:build path - add libraries - JUnit 4 - 下一步

2.创建Java类,进行单元测试。

此时的Java类要求:① 此类是public的 ②此类提供公共的无参的构造器

3.此类中声明单元测试方法。

此时的单元测试方法:方法的权限是public,没返回值,没形参

4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入:import org.junit.Test;

5.声明好单元测试方法以后,就可以在方法体内测试相关的代码。

6.写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test

说明:

1.如果执行结果没任何异常:绿条

2.如果执行结果出现异常:红条

常用设计模式:

23种经典的设计模式

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

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

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

面向对象有三大特点:

封装、继承、多态。

1.继承性:

继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。

对象的一个新类可以从现有的类中派生,这个过程称为类继承。

新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。

派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

2.封装性:

封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。

面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

3.多态性:

多态性是指允许不同类的对象对同一消息作出响应。

多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

4.抽象性:

抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。

抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。

抽象包括两个方面,一是过程抽象,二是数据抽象。

基本类型和包装类的值比较:

1.int和int之间,用==比较,肯定为true。

2.int和Integer比较,Integer会自动拆箱,== 和 equals都肯定为true。

3.int和new Integer比较,Integer会自动拆箱,调用intValue方法, 所以 == 和 equals都肯定为true。

4.Integer和Integer比较的时候,由于直接赋值的话会进行自动的装箱。

所以当值在[-128,127]中的时候,由于值缓存在IntegerCache中,那么当赋值在这个区间的时候,不会创建新的Integer对象,而是直接从缓存中获取已经创建好的Integer对象。

而当大于这个区间的时候,会直接new Integer。

4.1当Integer和Integer进行==比较的时候,在[-128,127]区间的时候,为true。不在这个区间,则为false。

4.2当Integer和Integer进行equals比较的时候,由于Integer的equals方法进行了重写,比较的是内容,所以为true。

5.Integer和new Integer,new Integer会创建对象,存储在堆中。而Integer在[-128,127]中,从缓存中取,否则会new Integer.所以Integer和new Integer进行==比较的话,肯定为false ; Integer和new Integer 进行equals比较的话,肯定为true。

6.new Integer和new Integer进行==比较的时候,肯定为false ; 进行equals比较的时候,肯定为true原因是new的时候,会在堆中创建对象,分配的地址不同,==比较的是内存地址,所以肯定不同

装箱过程是通过调用包装器的valueOf方法实现的。

拆箱过程是通过调用包装器的xxxValue方法实现的(xxx表示对应的基本数据类型)。

总结包装器的缓存:

Boolean:(全部缓存)

Byte:(全部缓存)

Character(<= 127缓存)

Short(-128 — 127缓存)

Long(-128 — 127缓存)

Integer(-128 — 127缓存)

Float(没有缓存)

Doulbe(没有缓存)

基本类型的取值范围:

byte:1字节 -128~127

short:2字节 -215~215-1

int :4字节 -231~231-1

long:8字节 -263~263-1

boolean:1字节 true false(java中不能以0或非0代替)

float: 4字节 -3.403E38~3.403E38

double:8字节 -1.798E308~- 4.9E324

char:2字节 ’\u0000‘~’ ’\uffff '(16进制的,换算过来即0~65535)

内部类:

  • 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。
  • 在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。
  • 内部类一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
  • 内部类的名字不能与包含它的外部类类名相同。
  • 分类:
    成员内部类(static成员内部类和非static成员内部类)
    局部内部类(不谈修饰符)、匿名内部类
  • 成员内部类作为类的成员的角色:
    和外部类不同,内部类还可以声明为private或protected;可以调用外部类的结构
    内部类可以声明为static的,但此时就不能再使用外层类的非static的成员变量
  • 成员内部类作为类的角色:
    可以在内部定义属性、方法、构造器等结构
    可以声明为abstract类,因此可以被其它的内部类继承
    可以声明为final的
    编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)
  • 【注意】
  1. 非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员内部类中才可声明static成员。
  2. 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式
  3. 成员内部类可以直接使用外部类的所有成员,包括私有的数据
  4. 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的
  • 如何使用局部内部类
    只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类
    但是它的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类的父类或父接口类型
  • 局部内部类的特点
    内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号,以及数字编号。
  • 只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类。
  • 局部内部类可以使用外部类的成员,包括私有的。
  • 局部内部类可以使用外部方法的局部变量,但是必须是final的。 由局部内部类和局部变量的声明周期不同所致。
  • 局部内部类和局部变量地位类似,不能使用public,protected,缺省,private
  • 局部内部类不能使用static修饰,因此也不能包含静态成员
  • 匿名内部类:
    匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。
  • 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
    格式:

new 父类构造器(实参列表)|实现接口(){ //匿名内部类的类体部分 }

匿名内部类的特点:

匿名内部类必须继承父类或实现接口

匿名内部类只能有一个对象

匿名内部类对象只能使用多态形式引用

匿名内部类的特点:

匿名内部类必须继承父类或实现接口

匿名内部类只能有一个对象

匿名内部类对象只能使用多态形式引用

  • 注意点:
  • 在局部内部类的方法中如果调用局部内部类所声明的方法中的局部变量的话,要求此局部变量声明为final的。
    jdk 7及之前版本:要求此局部变量显式的声明为final的
    jdk 8及之后的版本:可以省略final的声明
  • 成员内部类和局部内部类在编译以后生成的字节码文件:

格式:

  • 成员内部类:外部类$内部类名.class
  • 局部内部类:外部类$数字 内部类名.class

native关键字:

使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++等非Java语言实现的,并且被编译成了DLL,由java去调用。

(1)为什么要用 native 方法

java使用起来非常方便,然而有些层次的任务用java实现起来不容易,或者我们对程序的效率很在意时,问题就来了。

例如:有时 java应用需要与java外面的环境交互。

这是本地方法存在的主要原因,你可以想想 java需要与一些底层系统如操作系统或某些硬件交换信息时的情况。

本地方法正是这样一种交流机制:它为我们提供了一个非常简洁的接口,而且我们无需去了解java 应用之外的繁琐的细节。

(2)native 声明的方法,对于调用者,可以当做和其他Java方法一样使用,一个native method方法可以返回任何java 类型,包括非基本类型,而且同样可以进行异常控制。

native method 的存在并不会对其他类调用这些本地方法产生任何影响,实际上调用这些方法的其他类甚至不知道它所调用的是一个本地方法。

JVM 将控制调用本地方法的所有细节。如果一个含有本地方法的类被继承,子类会继承这个本地方法并且可以用 java语言重写这个方法(如果需要的话)。