@(Java)
面向对象编程期末考复习笔记
了解Java
-
Java具有面向对象、与平台(由系统OS和处理器CPU构成)无关、安全、稳定和多线程等优良特性。
-
Java编译与运行的过程:
java compile&run.png
-
Java程序有且只有一个主类,主类包含有
public static void main (String args[])
方法,args[] 是main方法的一个参数,是一个字符串类型的数组。 -
注释风格:单行注释
//
;多行注释/* */
。 -
Java的出现标志着真正的分布式系统的到来。
-
Java之父——James Gosling。
基本数据类型
- Java语言有8种基本数据类型,习惯上可分为4种:
- 逻辑类型:boolean
- 整数类型:byte(8位)、short(16位)、int(32位)、long(64位)
- 字符类型:char(16位)
- 浮点类型:float(32位,常量后面必须要有后缀f或F)、double(64位,允许省略后缀d或D)
8位(bit)= 1字节(byte)
char x = 97
==char x = 'a'
有些字符不能通过键盘输入到字符串或程序中,这是需要使用转义字符常量。
这些类型按精度从“低”到“高”排列为byte、short、char、int、long、float、double
- 当把级别低的变量的值赋给级别高的变量时,系统会自动完成数据类型的转换,如:
int x = 50; float y; y = x;
当把级别高的变量的值赋给级别低的变量时,必须使用显式转换运算,
转换格式为:(类型名)要转换的值,如:
int x = (int) 34.89; long y = (long) 56.98F; int z = (int) 1999L;
枚举
enum WeekDay { sun, mon, tue, wed, thu, fri, sat } WeekDay day = WeekDay.mon; WddkDay a[] = WeekDay.values();
for each
for( int i:a) { //a是一个数组,在for()里面必须进行变量声明,不能使用已经声明过的变量 System.out.println(i); }
数组的声明与创建
- 声明
声明数组包括声明数组的名字、数组元素的数据类型。
声明一维数组:数组元素的数据类型 数组名[];或 数组元素的数据类型[] 数组名;如float num[]
声明二维数组:数组元素的数据类型 数组名[][];或 数组元素的数据类型[][] 数组名;如char cat[][]
Java不允许在声明数组的方括号内指定数组元素的个数,数组变量的类型可以是Java的任一类型 - 创建
声明数组仅仅是给出了数组名字和元素的数据类型,要想真正使用数组还必须为它分配内存空间,即创建数组。
为数组分配内存空间的格式如下:数组名字 = new 数组元素的类型[数组元素的个数];如num = new float[4];
数组属于引用型变量,数组变量中存放着数组的首元素地址。 - 声明与创建可以一起完成(即只使用一条语句)。
和C语言不同的是,Java允许使用int型变量的值指定数组元素的个数,如int size = 30; double number[] = new double[size];
类与对象
- 重载:方法的返回类型和参数的名字不参与比较,也就是说,如果两个方法的名字相同,即使类型不同也必须保证参数类型或个数不同,返回值可以相同也可以不同。
- 重写:重写方法即可以操作继承的成员变量,也可以操作子类新声明的成员变量。如果子类想使用被隐藏的方法或方法,则必须使用super关键字。子类重写的方法和父类的某一方法具有相同的方法名、返回类型和参数表,子类方法的访问修饰权限不能低于父类的。
值得注意的问题:
声明类的成员变量时可以同时赋予初值,否则赋值语句只能出现在方法体中
实例方法既能对类变量进行操作也能对实例变量操作,而类方法只能对类变量进行操作
实例方法可以调用该类中的其他方法,类中的类方法只能调用该类的类方法
对象的内存模式:声明对象变量后就给对象分配内存,但此时内存中还没有数据,是一个空对象,创建对象后便分配了实例即内存有了数据。
对象在创建之后,就有了自己的变量,即对象的实体,但类中的实例方法(实例方法只被分配了入口地址)中的局部变量只有在方法被调用时才会被分配内存空间,方法执行完毕,局部变量便释放内存。局部变量在声明时如果没有初始化,就没有默认值,因此在使用局部变量之前要为其赋初值。
Java的对象在堆中分配内存,对象的引用是在栈中分配内存。
当参数是引用类型时,“传值”传递的是变量中存放的“引用”,而不是变量所引用的实体。
类的字节码文件被加载到内存,如果该类没有创建对象,类中的实例变量不会被分配内存。但是,类中的静态变量在该类被加载到内存时,就分配了相应的内存空间。对象共享静态变量。
实例方法和类方法的区别:当创建第一个对象时,类中的实例方法就分配了入口地址,当再创建对象时不再分配入口地址。也就是说,方法的入口被所有的对象共享,当所有的对象不存在时,方法的入口地址才会被取消;对于类方法,在该类被加载到内存时,就分配了相应的入口地址,类方法可以通过对象和类名调用,类方法的入口地址直到程序退出才被取消。
关于上转型对象
- 上转型对象不能操作子类新增的成员变量和新增的方法
- 上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或重写的方法,如果子类重写了父类的某个方法,当上转型对象调用该方法时一定是调用了子类重写的方法
- 可以将对象的上转型对象强制转换到一个子类对象,此时改子类对象有具备了子类的所有属性和功能
访问控制总览
可见度 | public | protect | private | 缺省(友好、默认) |
---|---|---|---|---|
同一类中可见 | 是 | 是 | 是 | 是 |
同一包中对子类可见 | 是 | 是 | 否 | 是 |
同一包中对非子类可见 | 是 | 是 | 否 | 是 |
不同包中对子类可见 | 是 | 是 | 否 | 否 |
不同包中对非子类可见 | 是 | 否 | 否 | 否 |
抽象类与接口
- abstract类的特点:
- 和普通的类相比,抽象类可以有abstract方法也可以有非abstract方法
- 不能用new运算符创建对象
- 如果一个abstract类是另一个abstract类的子类,那它可以重写abstract方法也可以不重写
- 接口
接口体中包含常量定义和方法定义两个部分
- 接口体中的方法必须是抽象方法
- 所有常量的访问权限一定都是public
- 所有抽象方法的访问权限一定都是public
- 如果一个类实现了某个接口,那么这个类必须重写该接口的所有方法,访问权限一定是public
- 接口可以被继承
如果一个类声明实现一个接口,但没有重写接口中的所有方法,那么这个类必须是abstract类
有关接口回调
String,StringBuffer,StringBuilder
这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面。
- 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。 - 再来说线程安全
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。 - 总结一下
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
流
Java三大特性
- 封装
java提高篇之理解java的三大特性——封装 - 继承
父类的静态方法不能被重写
当用子类创建对象时,不仅子类中声明的成员变量被分配了内存空间,而且父类的成员变量也被分配了内存空间。子类中还有一部分方法是从父类继承的,这部分方法可以操作未继承的变量
java提高篇之理解java的三大特性——继承 - 多态
Java实现多态有三个必要条件:继承、重写、向上转型。
java提高篇之理解java的三大特性——多态
内部类、匿名类、异常类
- 内部类内部类与外嵌类之间的重要关系如下:
- 内部类的外嵌类的成员变量在内部类仍然有效,内部类中的方法也能调用外嵌类的方法
- 在内部类的类体中不能声明类变量和类方法,外嵌类可以使用内部类作为成员变量的类型
- 内部类可以被修饰为static内部类,此时不能操作外嵌类中的实例成员变量
- 匿名类
- 直接使用一个类的子类的类体去创建一个子类对象,该类体叫匿名类
通过匿名类创建子类对象时,除了使用父类的构造方法还有类体
匿名类一定是内部类
匿名类中不能声明static成员变量和static方法 - 异常类
可以一try多catch
throws与throw:一个方法在声明时可以使用throws关键字声明要产生的若干个异常,并在该方法的方法体中具体给出产生异常的操作,即用相应的异常类创建对象,并使用throw关键字抛出该异常对象,导致该方法结束执行。其中catch的作用就是捕获throw抛出的异常。
finally子语句:无论try部分是否发生异常,finally子语句一定会被执行,除非执行程序退出代码
- 如果在try-catch语句中执行了return语句,那么finally语句仍会被执行
- 如果在try-catch语句中执行程序退出代码
System.exit(0);
,将不执行finally子语句
UML
public成员变量和方法: +
protect成员变量和方法: #
public成员变量和方法: +
private成员变量和方法: -
静态方法的方法名下用下划线
抽象类类名用斜体
接口:《interface》 People
- 泛化(实现抽象类)
空三角直线 - 关联(成员变量类型)
实心三角直线 - 聚合(集体与个体之间的关联关系)
实线加空心菱形 - 组合(个体与组成部分之间的关联关系)
实线加实心菱形 - 依赖(形参、局部变量或静态方法类型,方法返回值)
实心三角虚线 - 实现(实现接口)
空三角虚线 - 注释
泛型与集合框架
泛型类的声明:class People<E>//E可以是任何对象或接口,但不能是基本数据类型
泛型类中的泛型变量只能调用Object方法,即E类作为泛型的对象只能调用继承或重写Object类的方法,不能调用新增的方法。
泛型类可以使用泛型接口
Java泛型主要目的是建立具有类型安全的数据结构,如链表、散列表等数据结构,最重要的一个优点是在使用这些泛型类建立的数据结构时,不必进行强制类型的转换,即不要求进行运行时类型检查。
- LinkedList<>泛型类
迭代器:Iterator<> iter = list.iterator(); while(iter.hasNext()) {String str = iter.next();}
- Stack<>泛型类
- HashMap<>泛型类
- TreeSet<>
Java 泛型详解
JVM GC机制
Java中堆内存和栈内存详解
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存
在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。
堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器(GC机制)来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。
引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!
Java中堆内存和栈内存详解
浅析JAVA的垃圾回收机制(GC)
图解Java 垃圾回收机制
深入理解 Java 垃圾回收机制
其他
接口可以继承接口..但是要使用extends~而不是用implements如:interface a{}interface b extends a{}
抽象类可以实现接口..比如java.util中的AbstractCollection类就是实现的Collection接口
父类的静态方法不能被子类重写
Java线程面试题之进程和线程的区别
谈谈final、finally、finalize的区别
字符编码笔记:ASCII,Unicode 和 UTF-8
Java序列化
Java反射
Java Reflection(反射机制)详解
深入理解 Java 反射系列
Java 反射机制详解
Java注解
深入理解Java:注解(Annotation)自定义注解入门
秒懂,Java 注解 (Annotation)你可以这样学
深入浅出Java注解
深入理解Java注解类型(@Annotation)
Java多线程
进程是程序的一次动态执行过程,每个进程都有一个专用的内存区域,与此不同的是,线程间可以共享相同的内存单元(包括代码和数据),每个Java程序都有一个默认的主线程。
线程的四个生命周期:
- 新建
有了对应的内存空间和其他资源 - 运行
可以脱离创建它的线程独立开始自己的生命周期,start()方法通知JVM有新线程排队等待切换,run()会在得到CPU资源时立刻执行。 - 中断
4个原因:1)JVM将CPU资源切换给其他线程;2)sleep()方法,执行完后进入线程队列等待CPU资源;3)wait()方法,进入等待状态,执行后不会主动进入线程队列,必须由其他线程调用notify()通知它才会进入线程队列;4)线程使用CPU资源时执行某个操作(如执行读写操作)引起阻塞,进入阻塞状态的线程时线程是不能进入排队队列,只有引起阻塞的原因消除时才重新进入线程队列等待CPU资源,以便从中断处开始继续运行。 - 死亡
1)正常执行完毕;2)强制run()方法结束。
wait(), notify(), notifyAll()都是Object类中的final方法
线程优先级
- 继承Thread(单继承,不能扩展其他类)
重写run方法 - 使用Runnable接口
重写run方法
锁🔒
不可不说的Java“锁”事
Java锁机制了解一下
Java中的锁分类
设计模式
7大原则与23种设计模式
七大原则:
- 单一职责模式:每一个类应该专注于做一件事情。
- 里氏替换原则:超类存在的地方,子类是可以替换的。
- 依赖倒置原则:实现尽量依赖抽象,不依赖具体实现。
- 接口隔离原则:应当为客户端提供尽可能小的单独的接口,而不是提供大的总的接口。
- 迪米特法则:又叫最少知识原则,一个软件实体应当尽可能少的与其他实体发生相互作用。
- 开闭原则:面向扩展开放,面向修改关闭。
- 组合/聚合复用原则:尽量使用合成/聚合达到复用,尽量少用继承。原则: 一个类中有另一个类的对象。
设计模式之面向对象七大基本原则
Java设计模式:23种设计模式全面解析(超级详细)
JAVA设计模式总结之23种设计模式
网友评论