概述:java编程语言是纯粹的面向对象思想的语言。
现在程序开发有两个主流的方法:
(1)结构化程序设计,也叫面向过程程序设计,结构化程序设计主张以功能/步骤来进行软件设计。
如在解决问题时,主要是思考的是解决问题的步骤思路:
围棋游戏:
1.游戏开始,2,黑棋执行,3,绘制图片,4,判断输赢,5,白棋执行,6,绘制图片,7,判断输赢,8,返回2. 9,游戏结束
结构化程序设计是以函数为程序单元 ,从一个函数开始,调用其他普通函数,进行一些数据处理,一直调用下去。
设计思想:自顶而下,逐步精分,模块化
此种方式的编程语言有C,Basic,Pascal
(2)面向对象程序设计。
面向对象编程思想逐渐成熟起来。
它使用类,对象,继承,封装,消息等概念来进行程序设计。主要从现实世界的客观事物(即对象)出发来进行开发软件系统,
尽可能的运用人的自然思维方法 ,从客观事物来思考问题,认识问题。 从这些事物的本质特点,来抽象出系统所需要的类,
作为程序的基本单元。
围棋游戏:
黑白棋子及其行为,棋盘, 输赢规则
类是面向对象编程的基本单元,类含有一类事物的共同特征, 类可以产生多个对象,这些对象构成了程序中所需要的数据。
类是一类事物的抽象体现,而这些事物都有一些状态数据。即Field ,如,人,有身高,体重,姓名,性别,爱好等(程序设计时
,只关心业务所需要的数据), 类除了封装了一些事物的状态数据外,还提供了操作这些状态数据的方法(Method),实现逻辑。
类用来定义一种抽象数据类型。
Field,我们称之为成员变量,有些资料称之字段,也有些资料称之为属性,java有property关键字 是属性的。
从上述内容可以总结出
成员变量(状态数据)+方法(行为)定义=类的定义
此类方法的编程语言:C++,java,C#, Ruby
==================================
完成一个“猪八戒吃西瓜”这样的逻辑
面向过程: 函数吃 是核心
吃(猪八戒,西瓜)
面向对象: 一类事物的一个:猪八戒,吃是猪八戒的行为
一类事物的一个:西瓜
猪八戒.吃(西瓜)
组装电脑:
如果是主板,硬盘,内存条这样的大件,容易组装
---面向对象
如果是二极管,三极管,电路板这样的小件进行组装,
很难 ---面向过程
面向对象要比面向过程的粒度要大,相对来说容易,简单。
面向过程要比面向对象的性能要高,因为面向对象要进行对象的实例化,比较吃内存,吃性能。
===========================================
抽象数据类型:用一堆不同类型的状态数据来描述的一种新的事物。
reg: 描述电脑,
颜色, 尺寸, 型号, 主板, 内存, 硬盘,显卡
0xFF00FF 15.6 thinkpadT460 华硕 三星 希捷 , inter
0xFF00FF 15.6 lenovoE40 三星 三星 西数 , inter
这些事物的共同行为:
办公
playGame
play
用状态数据(成员变量)总结一类事物的共同特征,用方法总结一类事物的共同行为。
类的定义: =成员变量+方法
格式语法:
修饰词 class 类名{
type field1;
type field2;
.....
修饰词 返回值类型 method1(形参){}
修饰词 返回值类型 method2(形参){}
.....
}
=====================================
对象:类的实例化,即类中的个体
如何创建对象:使用关键字new
类名 引用变量 = new 类名();
引用变量,简称引用,存储的是对象的地址信息,我们可以理解为变量指向了堆中的对象
成员变量的调用:引用.成员变量名
方法的调用:引用.方法名(有参传参)
类与对象的关系:类是对象的模板,对象是类的实例化
内存管理机制:
jvm将其管理的内存分成三大主要区域:方法区,堆,栈
方法区:用来存储jvm加载的字节码文件的信息(类的信息)包含类的方法,方法只有一份,堆中的对象共享这份方法,在使用
非static修饰的方法时,需要对象来调用(即动态绑定到对象上)
堆: 用于存储引用类型所产生的对象,如果对象有成员变量,会给成员变量分配空间
栈:jvm在执行程序时,在栈中,会为每一个方法分配一个空间(即栈帧),用来存储方法的局部变量。当此方法结束后,栈帧消
失,释放内存
基本类型的变量与引用类型的变量:
值传递:
基本数据类型的变量里存储的是基本类型的数据,
int a = 5;
int b = a;//将a里的5复制了一份,传递给了b
址传递:
引用类型的变量里存储的是对象的地址信息
Car c = new Car();
Car d = c;//将c里的地址信息复制了一份,传递给了d
null与NullPointerException
null:是引用类型的默认值
NullPointerException:是程序在运行时产生的一种异常
如何产生的??
当引用变量没有指向任何对象时,调用了类型中的成员变量或者方法
reg:
Person p = null;
p.eat("面包");
p.name = "张三";
空指针异常:
java.lang.NullPointerException
在程序运行时,可能会出现此异常,出现的原因:
Car c = new Car();
System.out.println(c.color);//0
Car c = null;
System.out.println(c.color);//就会出现空指针异常
this关键字:(这个)
成员变量前 系统默认提供了this. 当形式参数与成员变量名称一致时,为了区分开,需要在成员变量前添加this. this指向的是
将要创建的那个对象,即,变量.方法()时的变量。当没有歧义时,this.可以省略不写
在构造器中:还可以使用this关键字调用本类中的其他构造方法
语法格式: this(有参传参)
只能在构造器中的首行首句上使用
方法:
概念:类的共同行为,封装了一段逻辑代码,在封装方法时,尽可能的只完成一项功能(避免将多个功能封装到一个方法内)
定义语法: 修饰词 返回值类型 方法名(....){
}
方法的使用:
方法属于对象的行为,应该使用:引用.方法,这些方法动态绑定到对象上 (没有static修饰的方法必须使用引用.方法(有参传参) )
方法签名:
方法名+形参列表=方法签名
形参列表:指的是形参的类型顺序列表
如:public void sum(int a,int b)
问:方法签名是: sum + int,int
public int eat(String food)
方法签名是:eat +String
方法的重载(overload):
在同一个类型中,方法名相同,参数列表(类型顺序)不同
在方法调用时,编译器会检查类的信息中是否有此方法签名的方法, c.sum(3,5):此时编译器检查类中是否有c.sum(int,int)这样的方法,如果有,编译通过, 没有,编译失败,并提示错误
构造方法(构造器):
是特殊的方法,作用是用来给成员变量(Field,字段,属性)初始化。
特殊在
(1)没有返回值这个位置
(2)方法名与类型相同
定义语法: 修饰词 类名(...){}
默认无参构造器:如果定义类时,没有添加构造方法,系统会默认提供一个公有的没有形式参数的构造方法
public Point(){}
注意:如果定义期间,提供了构造器,系统不再提供无参构造器。
有参构造器:因为构造器是用来给成员变量初始化的,为了方便,所以形式参数的名称都与成员变量一致。因此,在赋值时,this.不能省略。
构造器的调用:
只能是new关键字来调用 。
new 构造方法(有参传参)。
对象的实例化:是由new完成的(对象此时就存在了,但是成员变量都是默认值)
对象的成员变量初始化:是由new调用的构造器进行的(成员变量是第一次被赋值)
构造器的重载:
一个类中,可以有多个构造器。
方法名相同,参数列表不同
成员变量与局部变量的区别:
成员变量
定义位置:在方法外,类体中
默认值:有默认值,构造器中可以不对成员变量初始化
内存位置:在堆中
生命周期:从对象实例化开始出现,到对象消失
局部变量
定义位置:在方法内(包含小括号内的形参)
默认值: 没有默认值,必须初始化再使用
内存位置:在栈帧中
生命周期:从声明时开始,到方法结束后,栈帧消失时。
垃圾回收机制:(GC)
jvm的一个独有线程(程序),用于回收没有任何引用指向的对象。
System.out.println((new Person()).name);
上述产生的对象,以后再也无法使用,如果类似的这样情况有很多,对象来不及被处理,内存剩余空间就会越来越小,有可能出现内存溢出情况。因此需要一个处理机制,即垃圾回收机制。没有被引用的对象会被视为垃圾,等待GC被回收 (因为有垃圾绘制机制,所有java程序猿无需单向内存溢出或泄露情况)
继承:
java继承是定义一种的新的类型,从已有的类中吸收成员变量和方法,新的类型可以添加新的方法和成员变量。
优点:这种方式可以提高代码的复用性,缩短开发周期,减少开发费用。
现实世界中:通过分析多种类型,然后发现有一些共同特征和共同行为,再将这些种类,归纳为一种新类型
计算机语言中:先编写父类类型,再编写子类型,然后再有对象。
子类可以父类中继承一些成员变量,和方法。子类还可以添加自己的独有成员变量和方法。
子类:也叫派生类
父类:也叫超类,基类
关键字extends,用于继承语法
格式:
public class subClass extends SuperClass{
}
继承中的构造器:
子类不能继承父类的构造器,但是,子类中的构造器可以调用父类的构造器
语法: super(有参传参);
作用:可以更好的给继承过来的成员变量赋值
PS:子类中的构造器一定会有一个(至少有一个)调用了父类的构造器
父类中如果没有无参构造器,子类需要显式调用父类构造器
如果父类中有无参构造器,子类中的构造器可能隐式调用了父类的无参构造器.即:隐藏了super()
继承的传递性:
继承特征有传递特性,B类型继承了A类型的特征,C类型继承了B类型的特征。C类型也间接继承了A类型的特征
继承的另外一特点:
单继承: 一个子类只能继承一个父类。但是一个父类可以有多个子类
super()与this()的区别
相同点:都是调用构造器,而且必须放在首行首句(说明super()与this()不能同时出现在一个构造器中)。
不同点:super()是调用父类的构造器
this()是调用本类中其他构造器
方法的重写(override)(子类可以重新编写继承父类的方法)
子类可以继承父类的方法,在继承时,我们可以在子类中编写与父类中的方法名相同,参数列表也相同的方法。这就是重写。
(1)方法名相同,参数列表相同
(2)返回值类型可以相同,也可以是父类方法的返回值类型的子类型
(3)修饰词可以不变,或者可以比父类的修饰权限更大
父类型的变量可以引用子类型的对象:
变量能调用的方法与成员变量
如:
Animal a = new GoldFish();
Animal类型的变量a引用了子类型GoldFish的对象
符合人类的思维:
这条金鱼是动物
方法:
编译期绑定:
在编译过程中,变量只能调出本类型中的方法
在编译期间, 方法静态绑定到变量(变量类型)上
运行期绑定
在运行过程中,真正执行的方法的逻辑与对象的类型有关系。
简单说成:方法在运行期间,动态绑定到对象上。
成员变量:
变量调用出的成员变量一定是本类型中的成员变量(与编译期和运行期无关)
Object:是所有引用类型的顶级父类,
系统都会默认使引用类型extends Object.
此类中提供了常用的方法:
1:toString():
在Object中,返回的是类全名@HashCode值,即对象的内存堆中的位置信息
此方法会在输出变量时,或引用变量进行拼接时默认调用。
而查看地址信息,通常没有必要,我们通常要查看的是对象的成员变量信息
因此我们都需要重写toString()方法,用于查看对象的详情
格式:
"[成员变量1="+成员变量1+",成员变量2="+成员变量2+"]"
2:equals(Object obj)
Object类型中的此方法中的逻辑是比较调用者this与形参obj的地址信息是否相等。
简单说成:比较this与obj是不是同一个对象
所以在定义类型时,继承过来的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;
}
instanceof关键字:
作用是判断引用变量指向的对象是否属于某一类型
语法:
boolean f = 变量名 instanceof 类型名
访问权限控制修饰词
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)修饰类,
不能被继承,意义在 减少随意扩展功能的可能性,减少对系统的危害
(2)修饰变量:只能进行初始化,不能再被赋值
成员变量: 初始化的时机有两种
声明时同时初始化
在构造器中初始化
局部变量:使用前初始化即可
(3)修饰方法
不能被重写,意义在于: 可以避免某些子类"不经意"的重写
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;
}
}
抽象类:
因为继承的关系,子类的功能可以越来越具体,相对来说,父类更加一般化,通用化。因为父类封装了子类的共同行为,所以,在定义时,我们可以定义方法的逻辑。有的时候,在父类中无法完成子类的功能需求,此时,不如不写,即不写方法体,代码简单化。但是此方法必须使用abstract修饰,那么此类型也必须使用abstract修饰,即抽象类
1、抽象方法与抽象类
1)用abstract修饰的方法,不需要写方法体,但是得用分号来结尾
2)有抽象方法的类,必须使用abstract声明(修饰)
2、抽象类不能实例化
1) 抽象类不能创建对象,没有意义
2) 抽象类可以提供构造器(子类可继承其构造器)
3) 抽象类中可以没有抽象方法
4) abstract和final不能同时修饰一个类型
3、继承抽象类
1)若一个类继承了抽象类,那么这个类必须重写(实现)抽象类的所有抽象方法
2)若一个类没有实现抽象类的所有抽象方法, 那么这个类必须使用abstract修饰
4、抽象类的意义:
1)给不同的子类定义一个父类
2)抽象类可以封装子类的共同特征与共同行为
3)虽然子类方法可能有不能的实现逻辑,但是方法的定义一致。
接口:
有时我们需要从多个不相关的类中设计出一个子类型,而java继承是单继承的特点,无法满足我们的需求,所以,我们可以
使用接口来达到多继承的目的。 接口实际上就是一种规范制度。 (规范与规则的理解)
接口的特点:
(1)接口使用interface关键字,而不是class,但是我们可以理解成接口是特殊的抽象类
(2)接口里只能有抽象方法和常量 (1.8以后支持静态和默认方法)
(3)接口不能实例化,没有任何意义
(4)接口不能提供构造方法
接口中的常量:
默认使用修饰词为public static final
接口中的方法
默认使用public abstract
接口的实现
(1)子类需要实现接口中的所有抽象方法,
(2)使用implements关键字进行实现
(3)如果子类没有实现所有抽象方法,那么子类需要使用abstract修饰
(4)子类可以实现多个接口,接口间使用逗号分开
接口间的继承
(1)接口与接口之间可以使用继承。子接口继承了父接口的抽象方法
(2)支持多继承
======================================
多态:面向对象的特征之一 (重写属于多态,重载可以属于多态)
向上造型:
父类型的变量引用子类型的对象
(1) 父类型的变量指向不同的子类型对象,
调用的功能有不同的实现
Animal a = new Dog();
a.noise();//叫
a = new Cat();
a.noise();//叫
(2)不同的父类型变量指向同一个对象有不同的功能
ZhengYangDoor a = new ZhengYangDoor();
a.theftproof();//防盗
a.openDoor();//开门
InterA ia = a;
ia.theftproof();
向下造型:
将父类型(接口)的变量赋值给子类型或者是其他父类型(接口)的变量
Animal a = new Dog();
Dog dog =(Dog)a;
dog.吃骨头();
Cat cat = (Cat)a;//编译通过,语法正确,运行期间,造型错误
cat.扑捉老鼠();
两个类有共同的子类可以强转
运行期间有可能会发生类造型异常:java.lang.ClassCastException
为了避免出现错误:我们需要使用关键字instanceof来判断对象是不是要转换成的类型
if(a instanceOf Cat){
Cat cat = (Cat)a;
}
内部类:
是定义在一个类的内部的新类型。即内部类,另外一个类称之为外部类。
根据位置不同:
成员内部类
方法内部类(局部内部类)
带static修饰词的类 静态内部类
没有名称的类: 匿名内部类
最不常用的:方法内部类,静态内部类
方法内部类:定义在方法中,相当于局部变量,仅限于在方法中使用,定义时不能使用修饰词,可以直接访问外部类的非静态成员变量(也可以访问静态)
静态内部类:也是以类的成员来定义的,只不过多了一个修饰词static,可以直接访问外部类的静态成员
相对而言,成员内部类和匿名内部类比较常用。
成员内部类:以类的成员来定义,可以使用任何修饰词来修饰。
成员内部类访问外部类的成员
方法内隐藏一个指向外部类对象的引用。
外部类名.this.
成员内部类的使用:
创建对象:
要先创建一个外部类的对象outer
然后使用外部类对象去使用new调用内部类的构造器实例化
Inner inner = outer.new Inner(有参传参);
外部类访问成员内部类的成员
在外部类添加一个内部类的成员变量进行访问
匿名内部类:
没有名字的类型,写在外部类的方法中,只用一次,不需要定义类的结构,通常都是为了实现接口,抽象类或某一现有的类的子类,子类没有名称,所以称之匿名
想使用某个类,抽象类或接口的子类对象时,当我们只想使用一次,可以不用定义子类的结构,因此我们可以使用匿名内部类的写法,因为子类没有名称,因此写的时候可以向上造型,new 父类名称(可以有参){重写接口里的所有抽象方法或抽象类的所有抽象方法,或重写某一个实现方法};
面向对象的三大特征:
继承,封装,多态(抽象也被某些人认为是面向对象的第四大特征)
封装:
用于:
(1)一段逻辑代码 被封装到方法中。
(2)方法和成员变量定义在类体中
(3)成员变量的私有化,也是一种封装
优势: 提高代码的不可见性,增加安全性。可以通过多次调用方法来提高代码的复用性。维护性强
重写、重载属于多态。
类与类之间的关系
继承关系: extends
实现关系: implements
依赖关系: 有一定的偶然性,即类B以形式参数的方式通过类A的方法, 建立起的关系
聚合关系: 我与我的朋友 与 我一定我朋友的朋友
类A中可以有类B的成员变量
类B中也可以有类A的成员变量
===========================================
数组:
基本数据类型数组,元素是基本类型的数据。
引用数据类型数组,元素是对象
初始化的方法:
静态初始化:
元素类型[] 变量名 = {}
动态初始化:
(1)规定长度的
(2)不规定长度的
引用数据类型的数组使用规定长度的方式进行初始化时,
默认值是null;
如:
Cell[] cs = new Cell[10];
cs里有地址,数组对象的地址。此对象里有10个null。
cs[0] = new Cell(0,3);
第二个元素存储(0,4)的方法
cs[1] = new Cell(0,4);
PS:引用类型的数组对象内,存储的是元素对象的地址信息
===================================================
【
一个源文件中,只能有一个public修饰的类,而且此类必须与文件名一致。
其他类可以不用修饰词
main也需要在public修饰的类中,才能生效。
】
=========================================================
【在创建子类对象时,在内存中会不会产生父类对象??】
【答案1: 会产生,没有父类对象,哪来的子类对象】
【答案2: 不会产生,创建子类对象时,子类对象的成员变量包含两部分:
一部分为从父类中继承过来的
在成员变量前有默认的super.
一部分是自己本类中的
在成员变量前有默认的this.
如果子类中独有的与继承过来的成员变量重名时,必须
显式指定使用super.或者是this.
如果子类中没有与继承过来的成员变量相同名时,我们可以
隐式不写,或者使用super.与this.其中任意一个。
为了避免不必要的麻烦,子类的成员变量尽可能不要与父类的
成员变量同名
】
============================================================
【类有类名和类全名之分:
类名:即最短的名称
类全名:从包名开始写的名称
如: String 是类名
java.lang.String是类全名
】
============================================================
package: 包.
作用:用于管理源文件,区分类全名
命名规则:域名后缀.域名.项目名.模块名
声明位置:在源文件的首行首句。
类全名:从包开始写起的名称
常用的包:
java.lang.*,因为里面的类型非常常用。因此不需要导包
java.util.*,此包下封装了很多常用的工具类
java.io.*,此包下封装了io流的类型
java.net.*,此包下封装很多关于网络的多种类型
import: 导包关键字:
在class之上,package之下。
用于声明 类的 类全名,在逻辑中就可以使用短的类名。
优点: 可以减少代码的书写。
=====================================================