Java面向对象:
在之前的java的基础学习完我们进入了Java面向对象部分的学习
java是一门面向对象的语言、静态语言、编译型的语言
就好比我们吃面就可以看出来在面向过程的编程语言中分为以下过程:
吃面–烧水–和面–擀面–切面–下面–盛面–吃面
面向对象的编程语言
吃面:(要有对象、人、面、水、火)
吃面(行为)
这就是面向对象开发的不同接下来首先介绍
面向对象主要的三大特性
封装性:
内部的操作对外部而言不可见,内部操作都不可以直接使用的时候才是安全的。
继承性:
在已有结构的基础上进行功能的扩充
多态性:
在继承性基础上扩充而来的概念,指的是类型转换处理。
我们先简单介绍一下三大特性,在下面会详细说明。
接下来我们来了解一下类
类
类就是具备某些共同特征的实体的集合,它是一种抽象的数据类型,它是对所具有相同特征实体的抽象。在面向对象的程序设计语言中,类是对一类“事物”的属性与行为的抽象。例如动物就是类,里面有狗,猫,马等。
OO(Oriented Object):面向对象
OOP(Oriented Object Programming):面向对象的编程
面向对象开发的三大步骤
OOA():面向对象分析
OOT():面向对象测试
OOD():面向对象设计
面向对象的开发
1、定义类(分门别类的过程)
类是对某一类事物共性的抽象概念,对象是描述的一个具体的产物。
类是一个模板 对象才是一个实例,先有类然后有对象,
类有俩部分组成:成员属性(field),操作方法(method)
class 类名 {
// 类的静态特征,属性
//数据类型 属性;
// 方法
public void speak() {
System.out.println("学习使人快乐~~~");
}
}
2、得到对象(实例化对象)
对象类型 对象名称 = new 类型();
// 为属性赋值
对象名称.属性名称 = 属性值;
对象名称.方法名称([参数列表]);
类的命名规则,大驼峰法
class Person {
// 静态的特征
String name; //人的名称
int age; //年龄
double weight; // 体重
String sex; // 性别
/*
动态的特征,一般使用方法(函数)表示
*/
public String say() {
return "我好帅";
}
}
调用类的属性
实例化对象.成员属性
调用类的方法
实例化对象.方法名();
使用类构建对象
对象类型 对象名称 = new 类名称();
Person p1 = new Person();
内存分析:
head:堆内存:保存的是对象具体的信息。通过new关键字开辟新内存
stack:栈内存:保存的是一块堆内存地址
User user1 = new User(张三,23);
我们简单用一张图看一下上面这个对象的引用分析
当堆内存中的张三没有栈内存指向的时候,它就会变成垃圾,
上面中的张三这个对象是有名是user1,也存在匿名对象,直接通过new关键字构造,用完后被当作垃圾然后杯gc回收。
注意:
一个栈内存空间只能够保存一个堆内存的地址数据,如果发生更改,则之前的地址数据也会从此栈内存中彻底消失。
然后我们再简单说一下垃圾的概念。
垃圾
所有没有任何栈内存指向的堆内存空间就是垃圾
所有垃圾将被gc垃圾回收机制处理,这个我们不需要去深究,了解即可
然后我们再来扩充一下之前对变量的理解
变量
局部变量
定义在函数内部的变量,当函数调用完成,也就是函数弹栈之后,局部变量会消失,必须赋值使用,否则报错!
...
public int Test(int n){
int a = 10; //a就是局部变量
return a+n;
}
...
成员变量
成员变量定义在类中,成员变量也就是类中的属性,属于对象或者类的
成员方法
定义在类中方法(函数),所属对象或者类
构造函数(构造方法)
public 类名称(){
}
1、构造函数时用来初始化成员变量的
2、构造函数名称必须和类名称一致
3、构造函数不能写返回值
4、通过类得到 类型 对象名称 = new 类型(); 类型()本质就是在调用构造函数
5、如果定义了类,没写构造函数,jvm会自动帮助生成一个无参的构造函数
6、如果定义了构造函数,则jvm不会自动生成无参的构造函数
类的成员的初始化顺序:
在初始化对象的时候,首先初始化的是属性,之后才是构造函数
方法是在调用时才初始化的,调用完成后则出栈
static关键字
static是java的关键字
被static修饰的成员变量最先被加载内存中,可以在没有实例化对象的时候使用。
被static修饰的方法、变量都属于类本身,不属于对象,意味着可以直接通过类名来调用,可以在没有实例化对象的时候调用方法和成员变量。
静态方法中不能直接调用非静态方法(加载顺序)
被static修饰的变量,是存放在常量区最先加载
不能修饰类
普通代码块
用{}定义的结构,可以在一个方法中进行结构拆分,防止相同变量名带来的相互影响。
{
代码块
}
构造代码块
定义一样,只是定义在类中,构造代码块会优先构造方法执行,并且每次实例化新对象的时候都会调用构造代码块的代码。
静态代码块
使用static关键字定义的代码块,优先主方法执行
封装
封装就是指,将类的属性私有化,提供公开的set和get方法提供外界
访问或者设置的操作,叫做封装
权限访问修饰符
private // 私有 同类
默认(不写)缺省 // 只能同包 同类
protected // 受保护级别 同包 同类 子类(继承)
public // 公开的
如何实现封装
成员变量的封装将属性私有化,通过private访问修饰符修饰,类中的所有属性都必须用private进行封装,之后提供公开的get和set方法来操作属性
一个简单的java bean书写规范(可以描述一个人,一本书)
1,类名要有意义,可以明确的描述一类事物
2,类中所有属性用private封装,提供get set 方法
3,构造函数一般至少有两个,一个没有参数、一个全部参数的
4,类中不能有输出语句,所有内容必须返回。
5,发现类中没有属性存在的意义,定义方法不需要普通方法要用static修饰然后直接类名调用
继承
继承就是在已有类的功能上进行扩充,不能多重继承。
在java中,子类(派生类)继承父类,extends 关键字
当子类继承父类后,那么子类就自动的拥有了父类的一些方法和属性
继承规则:
1、public的修饰的都能被继承
2、protected修饰可以被继承
3、默认没有写,同包能访问
class 子类 extends 父类{
}
子类实例化对象,一定要先默认实例化对象父类,一定会实例化父类对象。
子类可以继承父类被public和protected修饰成员
1、在继承中,子类只能继承父类的被public或者protected修饰的方法或者属性
2、当父类方法不能满足子类的使用是,我们一般重写(覆盖)override方法
注意:重写方法是,修饰符访问权限可以扩大,不能缩小
3、子类再构造的时候,首先调用调用了父类的构造,之后才调用自身的构造
4、super是一个指针,指向子类的父类,
super() // 调用就是父类的构造
super.xxx // 调用了父类的属性或者方法
5、java中不允许使用多继承,Java是单继承机制
如果需要多继承机制,则使用接口解决
6、所有类都共有一个父类 Object
重写
子类定义了和父类方法名,参数类型和个数完全相同的方法,调用时用子类重写的方法,如果没有被重写的则调用父类的方法(优化父类的功能)
重写限制,
不能比父类更严格的访问权限
public > default > private
定义不参与重写
final关键字的使用
1、修饰变量,则该变量会变成常量(因为值再不能发生变化)
2、修饰方法,该方法不允许被重写(OverRide),一旦一个方法被final修饰,这个方法就是最后的方法,无法被子类重写
3、修饰类,当final修饰类的时候,该类则无法被继承,不能有子类
内部类:
类的内部定义的叫做内部类
内部类最大的作用就是,访问包含它的类的私有属性和方法
多态
多态就是对象的多种状态
方法的多态:重写,重载
对象多态性:
在面向对象中的多态指的是,父类引用,指向子类实例的现象,叫做多态
对象向上转型
父类引用指向子类的实例
此时可以使用父类来代替所有的子类
Animal animal_dog = new Dog();
Animal animal_cat = new Cat();
instanceof关键字:
判断实例是否是某个类的对象
对象 instanceof 类名
返回true/false
抽象方法(抽象类):
父类设计要考虑抽象类, 用abstract关键字进行定义
1、如果某个类中,某个方法没有实现,则需要使用abstract将该方法申明为抽象方法
2、一旦某个类中存在了抽象方法,该类必须申明为抽象类。
3、抽象类没办法直接实例化即使没有抽象方法也不能直接实例化,要利用对象多态性通过子类实例向上转型来实例化
4、子类一旦继承了抽象类,必须要实现抽象类中所有抽象方法,如果没有实现,则必须将子类申明为抽象类,继续向下传递这种特性
5、抽象类一定有构造方法,抽象类中可以提供static方法,不受到抽象类局限,可以直接类名调用
抽象类的应用
好处:
1、对子类方法可以统一管理
2、可以自身提供有一些普通方法并且这些普通方法可以调用抽象方法(这些抽象方法只有子类提供实现的时候才会生效)
接口(只包含抽象方法,和全局变量(jdk8后也可以加普通方法和静态方法))
接口描述的是一个公共的定义标准
用interface关键字声明的类,叫做接口一般在接口名前加I
注意:接口中的成员都必须是public的,即便没声明,也是public
接口中的方法都是抽象方法(接口中方法没有实现)
接口中不能有实现了的方法
接口可以多个实现( implements TestInterface, MyInterface2)
接口可以继承接口(重点掌握)public interface MyInterface2 extends TestInterface
1、接口需要被子类实现(implements),一个子类可以实现多个父接口
2、子类(如果不是抽象类)那么一定要重写接口中的全部抽象方法
3、接口对象可以利用子类对象向上转型进行实例化,
目的:一个子类可以实现多个接口,可以实现多继承。
Object类对象可以接收所有数据类型,包括基本数据类型,类对象,接口对象,数组。
接口的作用:
1、约束、规定
2、对java单继承的补充
一个抽象类可以实现多个接口,一个普通类只能继承一个抽象类并且可以实现多个父接口,但是要求先继承后实现。
接口是一种特殊的抽象类其中的abstract可以省略,抽象类则不可以。
Object
在Java,任何一个类,直接或者间接都是Objectd的子类
Object类定义在java.lang包
--------------------跟线程相关方法----------------
wait() ; // 让线程进入等待状态的方法
notify(); // 唤醒线程的方法
notifyAll(); // 唤醒所有等待线程的方法
--------------------------------------------------------
clone(); // 做对象拷贝的
Class cls = getClass(); // 获取对象的字节码文件
toString();
如果没有重写对象的toString方法,当我们直接打印对象的时候
package.ClassName@hashCode值
equals() // equals 比较两个对象是否相等
equals方法底层真正比较的是两个对象的内存地址()
public boolean equals(Object obj) {
return (this == obj);
}
在String类,我们可以直接调用equals比较两个字符串,因为String类重写Object的equals方法
hashcode() // 返回对象内存地址的hash值
一般比较对象,需要重写hashCode、equals
泛型 < T > (T:type) 或 < E >
为了解决ClassCastException异常问题,稍后会对异常进行说明。
本质:类中的属性或方法的参数与返回值的类型可以由对象实例化的时候动态决定
提示:关于默认的泛型类型:Object
泛型定义完成后可以在实例化对象的时候进行泛型类型的设置。
使用注意:
泛型之中只允许设置引用类型,如果要所有基本类型,只能用包装类
类名<E> 对象名 = new 类名<E>();
<?> :?是通配符,不允许修改,可以接收所有
<?extend 类名> :设置泛型上限,该泛型只能设置类或它的子类
<? super 类名> :设置泛型的下限,只能设置类或它父类
泛型接口
public interface IMessage<E>{
}
实现1:
public Message<E> implements IMessage<E>{
}
实现2:
IMessage<String> msg = new Message<String>();
包装类:
在Java中,每一个java的基本数据类型对应一个对象()
8种包装类:
int Interger
byte Byte
short Short
long Long
float Float
double Double
boolean Boolean
char Character
int a = 10;
Integer aa = new Integer(a); // 装箱操作
a = aa.intValue(); // 拆箱操作
jdk1.5之后自动完成拆装箱
Object obj = 1.1; //double自动装箱Double,向上转型为Object
Integer aa = a;
int b = aa; //aa的值范围 -128~127
转换类型的方法
Integer.parseInt("123");
字符串(String)对象
字符串不属于基本数据类型,是字符的数组
char c = 'a';
char[] arr = {'a', 'b', 'c'}; // "abc"
Java中,字符串是对象,由系统定义 java.lang.String类
final修饰
1、字符串的定义
String str = "字符串"; //产生匿名String对象
String str2 = new String("字符串"); //太费内存,因为首先在堆内存中开辟
新内存,之后又在string池中创建匿名对象
,之后让堆内存指向池中的匿名对象,所以
比较费内存
我们对以下String对象内存分析:
直接赋值的时候数据会在String池中保存
String str1 = "ma";
String str2 = "teng";
Strnig str3 = "teng";
用图来表示:
2、字符串的常见方法:
charAt() //获取指定索引位置的字符,下标从0开始
toCharArray() //将字符串变为字符数组
contains() //查询字符串中是否包含某个字符
indexOf() //查询某个字符串在该字符串中的首个索引位置
lastIndexOf() //查询最后个字符串在该字符串中的首个索引位置
trim() //去除字符串俩测的空格位
endwith() //查询是否以xxx结尾
startswith() //查询是否以xxx开始
substring() //切割字符串
equals() //是否相等
equalslgnoreCase() //忽略大小写比较
split() //切割字符串
length() //字符串的长度
replace() //字符串d替换
面向对象的主要内容还是三大特性:封装,继承,多态。其中封装继承都比较容易理解,多态需要在多使用的情况下理解,因为多态是在前俩特性的衍生。