面向对象和面向过程的思想对比 :
面向过程 :是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的。
优点:性能比面向对象高,因为类调用时需 要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展
面向对象 :是一种以对象为中心的编程思想,通过指挥对象实现具体的功能。
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
缺点:性能比面向过程低
类的组成是由属性和行为两部分组成
客观存在的事物皆为对象 ,所以我们也常常说万物皆对象。
总结: 多个对象在堆内存中,都有不同的内存划分,成员变量存储在各自的内存区域中,成员方法多个对象共用的 一份
总结 : 当多个对象的引用指向同一个内存空间(变量所记录的地址值是一样的) 只要有任何一个对象修改了内存中的数据,随后,无论使用哪一个对象进行数据获取,都是修改后的数据。
在程序执行的过程中,其值可以在某个范围内发生改变的量。从本质上讲,变量其实是内存中的一小块区域
成员变量包括实例变量和静态变量:
实例变量:独立于与方法之外的变量,无static修饰,声明在一个类中,但在方法、构造方法和语句块之外,
静态变量:独立于方法之外的变量,用static修饰。随着类的加载而加载
定义:Java中可以使用访问修饰符来保护对类、变量、方法的访问。Java 支持 4 种不同的访问权限。
分类
private : 在同一类内可见。使用对象:变量、方法。注意:不能修饰类(外部类)
default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。注意:不能修饰类(外部类)。
public : 对所有类可见。使用对象:类、接口、变量、方法
访问修饰符图
修饰符 |
当前类 |
同一包下 |
子类 |
其他包 |
private |
||||
default |
||||
protected |
||||
public |
this是指向对象本身的一个指针。
this的用法在java中大体可以分为3种:
super可以理解为是指向自己父类对象的一个指针,而这个超类指的是离自己最近的一个父类。
super也有三种用法:
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括属性抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
Java 面向对象编程三大特性:封装 继承 多态
封装:封装是把一个对象的属性私有化,隐藏内部的实现细节,同时提供一些可以被外界访问属性的方法(get和set)。通过封装可以使程序便于使用,提高复用性和安全性
继承:继承是使用已存在的类的定义作为基础,建立一个新的类,在添加新类的时候可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过继承可以提高代码复用性。继承是多态的前提。
关于继承如下 3 点请记住
多态性:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。多态提高了程序的扩展性。一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在程序运行期间才能决定。
Java实现多态有三个必要条件:继承、重写、向上转型。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
继承的特点:
注意:子类中所有的构造方法默认都会访问父类中无参的构造方法
子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因在于,每一个子类构造 方法的第一条语句默认都是:super()
问题:如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢?
1. 通过使用super关键字去显示的调用父类的带参构造方法
2. 子类通过this去调用本类的其他构造方法,本类其他构造方法再通过super去手动调用父类的带参的构造方法
注意: this(…)super(…) 必须放在构造方法的第一行有效语句,并且二者不能共存
1.2.1.2 继承中成员方法的访问特点
通过子类对象访问一个方法
1.2.1.3 super内存图
什么是多态: 同一个对象,在不同时刻表现出来的不同形态
class Animal {
public void eat(){
System.out.println("动物吃饭");
}
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Test1Polymorphic {
/*
多态的前提:
1. 要有(继承 \ 实现)关系
2. 要有方法重写
3. 要有父类引用, 指向子类对象
*/
public static void main(String[] args) {
// 当前事物, 是一只猫
Cat c = new Cat();
// 当前事物, 是一只动物
Animal a = new Cat();
a.eat();
}
}
class Fu {
public void show(){
System.out.println("Fu..show...");
}
}
class Zi extends Fu {
@Override
public void show() {
System.out.println("Zi..show...");
}
public void method(){
System.out.println("我是子类特有的方法, method");
}
}
public class Test3Polymorpic {
public static void main(String[] args) {
// 1. 向上转型 : 父类引用指向子类对象
Fu f = new Zi();
f.show();
// 多态的弊端: 不能调用子类特有的成员
// f.method();
// A: 直接创建子类对象
// B: 向下转型
// 2. 向下转型 : 从父类类型, 转换回子类类型
Zi z = (Zi) f;
z.method();
}
}
风险如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException
变量名 instanceof 类型
通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
abstract class Animal {
public abstract void eat();
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃肉");
}
public void watchHome(){
System.out.println("看家");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Test4Polymorpic {
public static void main(String[] args) {
useAnimal(new Dog());
useAnimal(new Cat());
}
public static void useAnimal(Animal a){ // Animal a = new Dog();
// Animal a = new Cat();
a.eat();
//a.watchHome();
// Dog dog = (Dog) a;
// dog.watchHome(); // ClassCastException 类型转换异常
// 判断a变量记录的类型, 是否是Dog
if(a instanceof Dog){
Dog dog = (Dog) a;
dog.watchHome();
}
}
}
当我们在做子类的共性功能提取时,有些方法在父类中并没有具体的体现,只在父类给出了抽象的类名.
抽象类的特点:
//抽象类的定义
public abstract class 类名 {}
//抽象方法的定义
public abstract void eat();
分工协作,专人干专事
如果将所有的类文件都放在同一个包下,不利于管理和后期维护,所以,对于不同功能的类文件,可以放在不同的包下进行管理
static的主要意义是在于创建独立于具体对象的变量或者方法。即使没有创建对象,也能使用属性和调用方法!
static修饰的特点 (记忆) :
static关键字注意事项 (理解):
变量是基本类型,不能改变的是值
变量是引用类型,不能改变的是地址值,但地址里面的内容是可以改变的
public static void main(String[] args){
final Student s = new Student(23);
s = new Student(24); // 错误
s.setAge(24); // 正确
}
public class Test {
/*
局部代码块
位置:方法中定义
作用:限定变量的生命周期,及早释放,提高内存利用率
*/
public static void main(String[] args) {
{
int a = 10;
System.out.println(a);
}
// System.out.println(a);
}
}
public class Test {
/*
构造代码块:
位置:类中方法外定义
特点:每次构造方法执行的时,都会执行该代码块中的代码,并且在构造方法执行前执行
作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性
*/
public static void main(String[] args) {
Student stu1 = new Student();
Student stu2 = new Student(10);
}
}
class Student {
{
System.out.println("好好学习");
}
public Student(){
System.out.println("空参数构造方法");
}
public Student(int a){
System.out.println("带参数构造方法...........");
}
}
public interface Inter {
public static final int NUM = 10;
public abstract void show();
}
class InterImpl implements Inter{
public void method(){
// NUM = 20;
System.out.println(NUM);
}
public void show(){
}
}
public class TestInterface {
/*
成员变量: 只能是常量 系统会默认加入三个关键字
public static final
构造方法: 没有
成员方法: 只能是抽象方法, 系统会默认加入两个关键字
public abstract
*/
public static void main(String[] args) {
System.out.println(Inter.NUM);
InterImpl interImpl=new InterImpl;
interImpl.method;
}
}
继承关系,只能单继承,但是可以多层继承
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
继承关系,可以单继承,也可以多继承
主要用于解决接口升级问题
public default 返回值类型 方法名(参数列表) {}
作用解决接口升级的问题
public default void show3() { }
public static 返回值类型 方法名(参数列表) { }
public static void show() {}
私有方法产生原因Java 9中新增了带方法体的私有方法,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义带方法体的默认方法和静态方法。这样可能就会引发一个问题:
当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性
private 返回值类型 方法名(参数列表) { }
private void show() { }
private static 返回值类型 方法名(参数列表) { }
private static void method() { }
内部类概念
在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类
/*
格式:
class 外部类名{
修饰符 class 内部类名{
}
}
*/
class Outer {
public class Inner {
}
}
内部类的访问特点 :
/*
内部类访问特点:
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
*/
public class Outer {
private int num = 10;
public class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
class Outer {
private int num = 10;
private class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
public class InnerDemo {
public static void main(String[] args) {
//Outer.Inner oi = new Outer().new Inner();错误写法
//oi.show();
Outer o = new Outer();
o.method();
}
}
静态成员内部类:
--访问外部类的父类指定成员 super.this
class Outer {
static class Inner {
public void show(){
System.out.println("inner..show");
}
public static void method(){
System.out.println("inner..method");
}
}
}
public class Test3Innerclass {
/*
静态成员内部类演示
*/
public static void main(String[] args) {
// 外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
oi.show();
Outer.Inner.method();
//test.Inner.show(); 错误的写法,必须要show为静态方法才可以
}
}
示例代码
class Outer {
private int num = 10;
public void method() {
int num2 = 20;
class Inner {
public void show() {
System.out.println(num);
System.out.println(num2);
}
}
Inner i = new Inner();
i.show();
}
}
public class OuterDemo {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
存在一个类或者接口,这里的类可以是具体类也可以是抽象类
new 类名 ( ) { 重写方法 }
new 接口名 ( ) { 重写方法 }
举例:
new Inter(){
@Override
public void method(){}
}
}
Inter i = new Inter(){
@Override
public void method(){
}
}
匿名内部类直接调用方法
interface Inter{
void method();
}
class Test{
public static void main(String[] args){
new Inter(){
@Override
public void method(){
System.out.println("我是匿名内部类");
}
}.method(); // 直接调用方法
}
}
//idea中打出new加空格 自动提示
/*
游泳接口
*/
interface Swimming {
void swim();
}
public class TestSwimming {
public static void main(String[] args) {
goSwimming(new Swimming() {
@Override
public void swim() {
System.out.println("铁汁, 我们去游泳吧");
}
});
}
/**
* 使用接口的方法
*/
public static void goSwimming(Swimming swimming){
/*
Swimming swim = new Swimming() {
@Override
public void swim() {
System.out.println("铁汁, 我们去游泳吧");
}
}
*/
swimming.swim();
}
}
代码示例:
/*
游泳接口
*/
interface Swimming {
void swim();
}
public class TestSwimming {
public static void main(String[] args) {
// 通过匿名内部类实现
goSwimming(new Swimming() {
@Override
public void swim() {
System.out.println("铁汁, 我们去游泳吧");
}
});
/* 通过Lambda表达式实现
理解: 对于Lambda表达式, 对匿名内部类进行了优化
*/
goSwimming(() -> System.out.println("铁汁, 我们去游泳吧"));
}
/**
* 使用接口的方法
*/
public static void goSwimming(Swimming swimming) {
swimming.swim();
}
}
有且仅有一个抽象方法的接口
省略的规则
如果代码块的语句只有一条,可以省略大括号和分号,和return关键字
public interface Addable {
int add(int x, int y);
}
public interface Flyable {
void fly(String s);
}
public class LambdaDemo {
public static void main(String[] args) {
// useAddable((int x,int y) -> {
// return x + y;
// });
//参数的类型可以省略
useAddable((x, y) -> {
return x + y;
});
// useFlyable((String s) -> {
// System.out.println(s);
// });
//如果参数有且仅有一个,那么小括号可以省略
// useFlyable(s -> {
// System.out.println(s);
// });
//如果代码块的语句只有一条,可以省略大括号和分号
useFlyable(s -> System.out.println(s));
//如果代码块的语句只有一条,可以省略大括号和分号,如果有return,return也要省略掉
useAddable((x, y) -> x + y);
}
private static void useFlyable(Flyable f) {
f.fly("风和日丽,晴空万里");
}
private static void useAddable(Addable a) {
int sum = a.add(10, 20);
System.out.println(sum);
}
}
异常的概述
异常就是程序出现了不正常的情况,程序执行过程中,出现非正常状况,最后导致JVM非正常停止
如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:
注意事项
在方法上进行显示声明,将来谁调用这个方法谁处理,若调用中没有解决办法,则给虚拟机来处理
throws |
throw |
用在方法声明后面,跟的是异常类名 |
用在方法体内,跟的是异常对象名 |
表示声明异常,调用该方法有可能会出现这样的异常 |
表示手动抛出异常对象,由方法体内的语句处理 |
示例代码
public class ExceptionDemo8 {
public static void main(String[] args) {
//int [] arr = {1,2,3,4,5};
int [] arr = null;
printArr(arr);//就会 接收到一个异常.
//我们还需要自己处理一下异常.
}
private static void printArr(int[] arr) {
if(arr == null){
//调用者知道成功打印了吗?
//System.out.println("参数不能为null");
throw new NullPointerException();
//当参数为null的时候,给调用者返回了一个错误,此时调用者就知道了他的错误,得写解决办法,若没有,则让虚拟机按虚拟机的办法来解决
//手动创建了一个异常对象,抛给了调用者,产生了一个异常
}else{
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
}
会把try中所有的代码全部执行完毕,不会执行catch里面的代码
那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了 当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码
那么try...catch就相当于没有写.那么也就是自己没有处理. 默认交给虚拟机处理.
出现多个异常,那么就写多个catch就可以了. 注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面
方法名 |
说明 |
public String getMessage() |
返回此 throwable 的详细消息字符串 |
public String toString() |
返回此可抛出的简短描述 |
public void printStackTrace() |
把异常的错误信息输出在控制台(字体是红色的) |
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
实现步骤
异常类
public class AgeOutOfBoundsException extends RuntimeException {
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
Collection集合和数组的区别:
都是容器,可以存储多个数据
方法名 |
说明 |
boolean add(E e) |
添加元素 |
boolean remove(Object o) |
从集合中移除指定的元素 |
boolean removeIf(Object o) |
根据条件进行移除 |
void clear() |
清空集合中的元素 |
boolean contains(Object o) |
判断集合中是否存在指定的元素 |
boolean isEmpty() |
判断集合是否为空 |
int size() |
集合的长度,也就是集合中元素的个数 |
boolean hasNext(): 判断当前位置是否有元素可以被取出 E next(): 获取当前位置的元素,将迭代器对象移向下一个索引位置
void remove(): 删除迭代器对象当前指向的元素
public class IteratorDemo1 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList<>();
//添加元素
c.add("hello");
c.add("world");
c.add("java");
c.add("javaee");
//Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
Iterator it = c.iterator();
//用while循环改进元素的判断和获取
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
介绍
public class MyCollectonDemo1 {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
//1,数据类型一定是集合或者数组中元素的类型
//2,str仅仅是一个变量名而已,在循环的过程中,依次表示集合或者数组中的每一个元素
//3,list就是要遍历的集合或者数组
for(String str : list){
System.out.println(str);
}
}
}
常用方法:
方法名 |
描述 |
void add(int index,E element) |
在此集合中的指定位置插入指定的元素 |
E remove(int index) |
删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) |
修改指定索引处的元素,返回被修改的元素 |
E get(int index) |
返回指定索引处的元素 |
public class MyListDemo {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//method1(list);
//method2(list);
//method3(list);
//method4(list);
}
private static void method4(List list) {
// E get(int index) 返回指定索引处的元素
String s = list.get(0);
System.out.println(s);
}
private static void method3(List list) {
// E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
//被替换的那个元素,在集合中就不存在了.
String result = list.set(0, "qqq");
System.out.println(result);
System.out.println(list);
}
private static void method2(List list) {
// E remove(int index) 删除指定索引处的元素,返回被删除的元素
//在List集合中有两个删除的方法
//第一个 删除指定的元素,返回值表示当前元素是否删除成功
//第二个 删除指定索引的元素,返回值表示实际删除的元素
String s = list.remove(0);
System.out.println(s);
System.out.println(list);
}
private static void method1(List list) {
// void add(int index,E element) 在此集合中的指定位置插入指定的元素
//原来位置上的元素往后挪一个索引.
list.add(0,"qqq");
System.out.println(list);
}
}
9.6 数据结构
9.7 List集合的实现类
LinkedList集合的特有功能:
方法名 |
说明 |
public void addFirst(E e) |
在该列表开头插入指定的元素 |
public void addLast(E e) |
将指定的元素追加到此列表的末尾 |
public E getFirst() |
返回此列表中的第一个元素 |
public E getLast() |
返回此列表中的最后一个元素 |
public E removeFirst() |
从此列表中删除并返回第一个元素 |
public E removeLast() |
从此列表中删除并返回最后一个元素 |