一、面向对象
1、概述:java编程语言是纯粹的面向对象思想的语言。
程序开发有两个主流的方法:
(1)结构化程序设计,也叫面向过程程序设计:
1)结构化程序设计主张以功能/步骤来进行软件设计。如在解决问题时,主要是思考的是解决问题的步骤思路。
2)结构化程序设计是以函数为程序单元 ,从一个函数开始,调用其他普通函数,进行一些数据处理,一直调用下去。
3)设计思想:自顶而下,逐步精分,模块化。此种方式的编程语言有C,Basic,Pascal
(2)面向对象程序设计:
1)面向对象编程思想逐渐成熟起来。它使用类,对象,继承,封装,消息等概念来进行程序设计。主要从现实世界的客观事物(即对象)出发来进行开发软件系统,尽可能的运用人的自然思维方法 ,从客观事物来思考问题,认识问题。 从这些事物的本质特点,来抽象出系统所需要的类,作为程序的基本单元。
类
1)类是面向对象编程的基本单元,类含有一类事物的共同特征,类可以产生多个对象,这些对象构成了程序中所需要的数据。
2)类是一类事物的抽象体现,而这些事物都有一些状态数据。即Field ,如,人,有身高,体重,姓名,性别,爱好等(程序设计时,只关心业务所需要的数据)。
3)类除了封装了一些事物的状态数据外,还提供了操作这些状态数据的方法(Method),实现逻辑。
4)总结:成员变量(状态数据)+方法(行为)定义=类的定义。此类方法的编程语言:C++,java,C#, Ruby
面向对象与面向过程的区别:
1)面向对象要比面向过程的粒度要大,相对来说容易,简单。
2)面向过程要比面向对象的性能要高,因为面向对象要进行对象的实例化, 比较吃内存,吃性能。
抽象数据类型:
1)用一堆不同类型的状态数据来描述的一种新的事物。
reg: 描述电脑,
颜色, 尺寸, 型号, 主板, 内存, 硬盘, 显卡
0xFF00FF 15.6 thinkpadT460 华硕 三星 希捷 , inter
0xFF00FF 15.6 lenovoE40 三星 三星 西数 , inter
这些事物的共同行为:办公、playGame、play
2)用状态数据(成员变量)总结一类事物的共同特征,用方法总结一类事物的共同行为。
类的定义:=成员变量+方法
格式语法:
修饰词 class 类名{
type field1;
type field2;
.....
修饰词 返回值类型 method1(形参){}
修饰词 返回值类型 method2(形参){}
.....
}
定义一个类型:Person
成员变量(状态数据-共同特征):name,gender,age,birth,idcard,isMarry;方法(行为):eat()、sleep()、work()、sport()
public class Person {
String name;
char gender;
int age;
String birth;
String idcard;
boolean isMarry;
public void eat(String food){
System.out.println(name+"喜欢吃"+food);
}
public void sleep(){
System.out.println("生日是"+birth+"的,性别是"+gender);
}
public void work(){
System.out.println("姓名为"+name+"生日为"+birth+"的人不想上班");
}
public void sport(){
System.out.println("名为"+name+",性别为"+gender+"的人喜欢健身");
}
public String info(){
String str = "[nmae="+name+",gender="+gender+
",age="+age+",birth="+birth+",idcard="+idcard+",isMarry="+isMarry+"]";
return str;
}
}
对象:
类的实例化,即类中的个体
如何创建对象:使用关键字new
类名 引用变量 = new 类名();
引用变量:简称引用,存储的是对象的地址信息
1)成员变量的调用:引用.成员变量名
2)方法的调用:引用.方法名(有参传参)
类与对象的关系:类是对象的模板,对象是类的实例化
内存管理机制:
1)jvm将其管理的内存分成三大主要区域:方法区,堆,栈
2)方法区:当程序运行时,将所需要的class文件(类的信息)加载到此区间
3)堆: 用于存储引用类型所产生的对象,如果对象有成员变量,会给成员变量分配空间
4)栈:方法内的变量(局部变量)是在栈中开辟的
基本类型的变量与引用类型的变量:
值传递:
基本数据类型的变量里存储的是基本类型的数据,
int a = 5;
int b = a;//将a里的5复制了一份,传递给了b
址传递:
引用类型的变量里存储的是对象的地址信息
Car c = new Car();
Car d = c;//将c里的地址信息复制了一份,传递给了d
空指针异常:
java.lang.NullPointerException
在程序运行时,可能会出现此异常,出现的原因:当引用变量没有指向任何对象时,调用了类型中的成员变量或者方法
Car c = new Car();
System.out.println(c.color);//0
Car c = null;
System.out.println(c.color);//就会出现空指针异常
reg:
Person p = null;
p.eat("面包");
p.name = "张三";
null:是引用类型的默认值
this(这个)关键字:
1、在普通方法或构造器中,操作的成员变量如果与局部变量名称相同时,为了避免出现歧义,应该在成员变量前使用this.进行区分;当没有歧义时,this.可以省略不写。
2、this指向的是将要创建的那个对象,即:变量.方法()时的变量。
3、在构造器中:还可以使用this关键字调用本类中的其他构造方法。
语法格式: this(有参传参),只能在构造器中的首行首句上使用
方法:
1、概念:类的共同行为,封装了一段逻辑代码,在封装方法时,尽可能的只完成一项功能(避免将多个功能封装到一个方法内)。
2、方法的使用:方法属于对象的行为,应该使用:引用.方法,这些方法动态绑定到对象上。
3、方法签名:方法名+形参列表=方法签名;形参列表:指的是形参的类型顺序列表。
如:public void sum(int a,int b)
方法签名是: sum + int,int
public int eat(String food)
方法签名是:eat +String
4、方法的重载(overload):在同一个类型中,方法名相同,参数列表不同。
注:在方法调用时,编译器会检查类的信息中是否有此方法签名的方法。
内存管理机制:
1、概念:jvm将内存分成三大主要区域,堆,栈,方法区,用来存储数据。
1)堆(heap): 存储new出来的对象,给成员变量分配空间。
2)栈(stack):jvm在执行程序时,在栈中,会为每一个方法分配一个空间(即栈帧),用来存储方法的局部变量。
3)方法区: 用来存储jvm加载的字节码文件的信息(类的信息)包含类的方法,方法只有一份,堆中的对象共享这份方法,在使用非static修饰的方法时,需要对象来调用(即动态绑定到对象上)。
4)栈帧:是栈中的空间。当程序执行到某一个方法时,jvm专门为此方法开辟的一块独有空间,此方法内的局部变量都在此栈帧中,当此方法结束后,栈帧消失,释放内存
构造方法(构造器):
1、概念:构造器是特殊的方法,作用是用来给成员变量(Field,字段,属性)初始化。
注:特殊在(1)没有返回值这个位置,(2)方法名与类型相同。
如: 点
public class Point{
int x;
int y;
修饰词 类型名(){}
....普通方法
}
2、默认无参构造器:如果定义类时,没有添加构造方法,系统会默认提供一个公有的没有形式参数的构造方法public Point(){}
注:如果定义期间,提供了构造器,系统不再提供无参构造器。
3、有参构造器:因为构造器是用来给成员变量初始化的,为了方便,所以形式参数的名称都与成员变量一致。因此,在赋值时,this.不能省略。
4、构造器的调用:只能是new关键字来调用的。new 构造方法(有参传参)。
对象的实例化:是由new完成的(对象此时就存在了,但是成员变量都是默认值)。
对象的成员变量初始化:是由new调用的构造器进行的(成员变量是第一次被赋值)。
5、构造器的重载:一个类中,可以有多个构造器。方法名相同,参数列表不同。
成员变量与局部变量的区别:
成员变量:
定义位置:在方法外,类体中。
默认值:有默认值,构造器中可以不对成员变量初始化。
内存位置:在堆中。
生命周期:从对象实例化开始出现,到对象消失。
局部变量:
定义位置:在方法内(包含小括号内的形参)。
默认值: 没有默认值,必须初始化再使用。
内存位置:在栈帧中。
生命周期:从声明时开始,到方法结束后,栈帧消失时。
垃圾回收机制:(GC)
概念:jvm的一个独有线程(程序),用于回收没有任何引用指向的对象。没有被引用的对象会被视为垃圾,等待GC被回收。
例如:System.out.println((new Person()).name);
数组:
引用数据类型数组,元素是对象。【基本数据类型数组,元素是基本类型的数据。】
初始化的方法:
1、静态初始化: 元素类型[] 变量名 = {}。
2、动态初始化:
(1)规定长度的: 元素类型[] 变量名 = new 元素类型[数组的长度];
(2)不规定长度的: 元素类型[] 变量名 = new 元素类型[]{};
(3)引用数据类型的数组使用规定长度的方式进行初始化时,默认值是null;
(4) 引用类型的数组对象内,存储的是元素对象的地址信息。
如:
Cell[] cs = new Cell[10];
cs里有地址,数组对象的地址。此对象里有10个null。
第一个元素存储(0,3)的方格
cs[0] = new Cell(0,3);
第二个元素存储(0,4)的方法
cs[1] = new Cell(0,4);
继承:
概念:java继承是定义一种新的类型,从已有的类中吸收成员变量和方法,新的类型可以添加新的方法和成员变量。
关键字extends,用于继承语法
格式:
public class subClass extends SuperClass{
}
优点:这种方式可以提高代码的复用性,缩短开发周期,减少开发费用。
继承中的构造器:
1、概念:子类不能继承父类的构造器,只能调用父类的构造器(使用super(有参传参))。
作用:可以更好的给继承过来的成员变量赋值。
2、子类中的构造器,至少有一个调用了父类的构造器。
注:父类中如果没有无参构造器,子类需要显式调用父类构造器。如果父类中有无参构造器,子类中的构造器可能隐式调用了父类的无参构造器.即:隐藏了super()。
super()与this()的区别:
1、相同点:都是调用构造器,而且必须放在首行首句。
2、不同点:super()是调用父类的构造器;this()是调用本类中其他构造器。
继承的传递性:
概念:继承特征有传递特性,B类型继承了A类型的特征,C类型继承了B类型的特征。C类型也间接继承了A类型的特征。
继承中的单继承: 一个子类只能继承一个父类。但是一个父类可以有多个子类。
注:一个源文件中,只能有一个public修饰的类,而且此类必须与文件名一致。其他类可以不用修饰词;main也需要在public修饰的类中,才能生效。
方法的重写(override):
1、概念:子类可以继承父类的方法,在继承时,我们可以在子类中编写与父类中的方法名相同,参数列表也相同的方法。这就是重写。
(1)父子类关系,方法名相同,参数列表相同。
(2)返回值类型可以相同,也可以不同[子类方法的返回值类型必须是父类方法的返回值类型的子类]。
(3)修饰词可以不变,或者可以比父类的修饰权限更大。
父类型的变量可以引用子类型的对象:
如:
Animal a = new GoldFish();
Animal类型的变量a引用了子类型GoldFish的对象
符合人类的思维:这条金鱼是动物
变量能调用的方法与成员变量:
1、方法:
编译期: 变量只能调用出本类型中的方法。
运行期: 变量调用出方法执行逻辑与对象的类型有关。
2、成员变量:
变量调用出的成员变量一定是本类型中的成员变量
Object:
1、Object是所有引用类型的顶级父类,系统都会默认使引用类型extends Object。
此类中提供了常用的方法:
1、 toString():
在Object中,返回的是类全名@HashCode值,即对象的内存堆中的位置信息。
(2) 此方法会在输出变量时,或引用变量进行拼接时默认调用。
(3) 而查看地址信息,通常没有必要,我们通常要查看的是对象的成员变量信息。
因此我们都需要重写toString()方法,用于查看对象的详情。
格式:”[成员变量1=”+成员变量1+”,成员变量2=”+成员变量2+”]”
注:类有类名和类全名之分:
类名:即最短的名称
类全名:从包名开始写的名称
如:
String 是类名
java.lang.String是类全名
2、equals(Object obj)
(1) Object类型中的此方法中的逻辑,是比较调用者this与形参obj的地址信息是否相等。
简单说成:比较this与obj是不是同一个对象。
(2) 所以在定义类型时,继承过来的equals方法 我们要重写。
重写规则:
1)查看传进来的obj是不是null
if(obj==null){
return false;
}
2)查看传进来的obj是不是this
if(obj==this){
return true;
}
3)查看传进来的obj是不是本类型
if(obj.getClass()!=this.getClass()){
return false;
}
可以改成
if(!(obj instanceof Person)){
return false;
}
注:==与equals()方法的区别???
==是比较地址信息,即比较是否为同一个对象。equals用来比较两个变量的对象是否相似
instanceof关键字:
1、作用:是判断引用变量指向的对象是否属于某一类型。
2、语法: boolean f = 变量名 instanceof 类型名
package:
作用:用于管理源文件,区分类全名
命名规则:域名后缀.域名.项目名.模块名
声明位置:在源文件的首行首句。
常用的包:
java.lang.*,因为里面的类型非常常用。因此不需要导包
java.util.*,此包下封装了很多常用的工具类
java.io.*,此包下封装了io流的类型
java.net.*,此包下封装很多关于网络的多种类型
import: 导包关键字
在class之上,package之下。用于声明 类的 类全名,在逻辑中就可以使用短的类名。
优点: 可以减少代码的书写。
访问权限控制修饰词:
private,protected,public,默认的(default)
修饰类时:
外部类:可以使用public和默认的。
内部类:可以使用public,protected,默认的,private。
修饰成员变量:四个都可以进行修饰,可见性不一样。
本类中 同包下 不同包子类中 其他
public true true true true
protected true true true
default true true
private true
注:在实际开发中,成员变量要尽可能的设置成不可见,好处是,提高代码的安全性。即用private修饰。为了在其他类中可以对成员变量进行重新设置值或者获取值我们可以定义相应成员变量的共有方法来进行操作。
public void setName(String name){
this.name = name;//修饰成员变量的值
}
public String getName(){
return name;
}
修饰方法:与修饰成员变量的可见性一致。
方法的重写: 子类不能重写父类的私有方法。
修饰词final:
(1)修饰类,被final修饰的,不能再有子类了。不能被继承,意义在 减少随意扩展功能的可能性,减少对系统的危害。
(2)修饰成员变量可以直接初始化,也可以在构造器中初始化,不能再其他任何地方再次赋值;修饰局部变量只能初始化一次(使用前初始化即可)。
(3)修饰方法被final修饰的方法,不能再子类中重写。意义在于: 可以避免某些子类”不经意”的重写。
方法的重载(overload)与重写(override)
重载:在同一个类中,方法名相同,参数列表不同。
重写:子类重写父类的方法,方法名相同,参数列表相同;返回值类型可以相同,也可以是父类方法的返回值类型的子类;修饰词可以相同,或者权限比父类方法的权限大。
static:英文含义:静态
1、修饰成员变量
(1)修饰的成员变量,不属于对象的数据结构
(2)静态变量属于类的,通常使用类名去调用
(3)静态变量与类的信息一起存在方法区中,只存在一份,是对象的公共资源。
2、修饰方法
(1)通常的方法都是与具体对象有关系,即对象的方法(行为)。
(2)如果是static方法则与对象毫无关系,是类的方法。通常用类名去调用,常常与参数有关系。
(3)static方法内因为无法使用this关键字,因此不能直接访问非静态成员。
(4)static方法的作用一般都用于设计成”工具方法”和”工厂方法”。
如:
Arrays.sort(数组名);
Math.random();
Math.sqrt(参);
Math.abs(参);
Math.sin(参数);
3、static修饰代码块
static{
代码逻辑
}
静态块存储在方法区中,只加载一次,与对象无关。执行时机为加载类的信息期间,可以理解为在实例化之前。
作用:通常用于加载程序中所需要的静态资源:如:图片,音频,视频等。
非静态代码块与静态代码块,成员变量,方法都是类的成员。
语法:
{
}
运行时机:在实例化之前执行,每次实例化之前都会执行一次。
常量:
一般都是一些特殊值。一般都使用成员变量,修饰词为public static final,声明时必须初始化。
命名规则: 字母全都大写
如: Math.PI
设计模式之单例模式:
需求:在程序中的任何地方,我们想要获取某一个类的唯一对象。我们称之为类的单例。
Singleton
(1)提供一个私有的静态的本类型的成员变量。
(2)构造器私有化。
(3)提供公有的静态的方法获取本类中创建的实例。
饿汉写法: 加载期间就实例化对象
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
懒汉写法: 调用方法时才创建对象
public class Singleton{
private static Singleton instance ;
private Singleton(){}
public static Singleton getInstance(){
if(instance ==null){
instance = new Singleton();
}
return instance;
}
}
抽象类:
概念:java创建了一种专门用来当父类的类,在父类中无法完成子类的功能需求,此时,不如不写,即不写方法体,代码简单化。但是此方法必须使用abstract修饰,那么此类型也必须使用abstract修饰,即抽象类。
1、抽象方法与抽象类
1)用abstract修饰的方法,不需要写方法体,但是得用分号来结尾
2)有抽象方法的类,必须使用abstract声明(修饰)
2、抽象类不能实例化
1)抽象类不能创建对象,没有意义
2)抽象类可以提供构造器
3)抽象类中可以没有抽象方法
4)abstract和final不能同时修饰一个类型
3、继承抽象类
1)若一个类继承了抽象类,那么这个类必须重写(实现)抽象类的所有抽象方法
2)若一个类没有实现抽象类的所有抽象方法, 那么这个类必须使用abstract修饰
4、抽象类的意义:
1)给不同的子类定义一个父类
2)抽象类可以封装子类的共同特征与共同行为
3)虽然子类方法可能有不能的实现逻辑,但是方法的定义一致。
接口:
1、概念:
接口是java中最重要的概念之一,它可以被理解为一种特殊的类,是由全局常量和公共的抽象方法组成。
2、接口的特点:
(1)接口使用interface关键字,而不是class,但是我们可以理解成接口是特殊的抽象类。
(2)接口里只能有抽象方法和常量。
(3)接口不能实例化,没有任何意义。
(4)接口不能提供构造方法。
3、接口的实现:
(1) 使用implements关键字进行实现。
(2)子类需要实现接口中的所有抽象方法。
(3)如果子类没有实现所有抽象方法,那么子类需要使用abstract修饰。
(4)子类可以实现多个接口,接口间使用逗号分开。
4、接口间的继承:
(1)接口与接口之间可以使用继承,子接口继承了父接口的抽象方法。
(2)支持多继承。
接口中的常量:默认使用修饰词为public static final。
接口中的方法:默认使用public abstract。
多态:面向对象的特征之一
1、多态的两种体现形式:
(1)方法的重载与重写。
(2)对象的多态性。
2、向上造型:父类型的变量引用子类型的对象
(1) 父类型的变量指向不同的子类型对象,调用的功能有不同的实现。
(2)不同的父类型变量指向同一个对象有不同的功能。
3、向下造型:
将父类型(接口)的变量赋值给子类型或者是其他父类型(接口)的变量。
类造型异常:
运行期间有可能会发生类造型异常:java.lang.ClassCastException。
为了避免出现错误:我们需要使用关键字instanceof来判断,对象是不是要转换成的类型。
if(a instanceOf Cat){
Cat cat = (Cat)a;
}
内部类:
是定义在一个类的内部的新类型。即内部类,另外一个类称之为外部类。
1、根据位置不同可分为:成员内部类、方法内部类(局部内部类)、静态内部类、匿名内部类。
2、不常用的:方法内部类、静态内部类
(1)方法内部类:定义在方法中,相当于局部变量,仅限于在方法中使用。定义时不能使用修饰词,可以直接访问外部类的非静态成员变量。
(2)静态内部类:也是以类的成员来定义的,只不过多了一个修饰词static,可以直接访问外部类的静态成员。
3、常用的:成员内部类、匿名内部类
(1)成员内部类:以类的成员来定义,可以使用任何修饰词来修饰。
1)成员内部类访问外部类的成员:
方法内隐藏一个指向外部类对象的引用。外部类名.this.
外部类访问成员内部类的成员:
在外部类添加一个内部类的成员变量进行访问
2)成员内部类的使用:
要先创建一个外部类的对象outer,然后使用外部类对象去使用new调用内部类的构造器实例化。
(2)匿名内部类:
没有名字的类型,写在外部类的方法中,只用一次,不需要定义类的结构。
通常都是为了实现接口,抽象类或某一现有的类的子类,子类没有名称,所以称之匿名。