一、面向对象OO:(类+对象)==表格
- 所有的数据,都可以看成是表格,只有静态和动态
- 以类的方式组织代码,以对象的方式组织(封装)数据。
1. 面向过程:执行者思维(简单问题)
- 可视?
- 步骤1,2,3…
2. 面向对象:设计者思维(复杂问题)
- 先思考解决问题需要分哪些类,再对类进行单独思考,类中间是细节考虑的东西。
- 面向对象包括(封装了)面向过程。
- 不可视?
- 协作问题。
二、类
-
即:属性(私有)+方法(public、set、get)== 表的结构class
静态类、模板、设计者 -
包含一堆可以不同类型的变量。
1.定义、创建、初始化使用
- 不是每一个创建的类都需要一个main()函数,只是单纯的需要一个方法,放置一堆对象,并且进行相关的操作。
- 一个project一般只有一个main()函数。
public class Car {
}
class type{
}
- p1、p2对象就是Person类的具体实例。
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1.name);
- 用new创建的情况下,刚刚创建好的对象,会进行①分配内存空间+②默认进行初始化(null、0、false)+③对类中构造器调用
p1.name = "小明";
p1.age = 18 ; //静态初始化
System.out.println(p1.name+"t"+p2.name);
System.out.println(p1.age+"t"+p2.age);
♥♥构造器:constructor四个要点:
- 对对象的属性进行初始化工作。
- 关键词new来 调用:本质:调用构造器。(new 调用构造的方法)
- 有调用,有return返回值
- 构造器的方法、名称必须与类相同(大小写也得相同)
方法:是公用的。 - 隐式构造出:如果没有定义该构造器,idea会自动定义添加一个 无参的 (有初始值,没有返回值return,也不能写void) 构造方法。(默认一个隐式参数,this)
this.id指的是上面这个 类的id。
- 定义有参构造之后,如果要使用无参构造,显示地定义一个无参的构造器。
三.对象object,instance
动态的、过程、方法。 是具体实例
- 一个对象:包含上述类中的每一个变量。这么一片叫一个对象。
- 可以有多个对象。
四、面向对象的内存分析 ♥
目的:理解对象
java虚拟机内存模型概念:
1.线程
- 栈stack:连续的,动态的
①程序计数器:记录执行到哪一步,下次执行知道从哪里开始。
②java虚拟机栈:栈帧(JVM为每个线程创建一个栈)
③本地方法栈:操作系统
④main()在栈底
2.堆
- heap(存数组):不连续的,新建的new
划分不同分区,根据需求不同,分得不同的时间空间,(传值), 方便垃圾回收。
(不动的)
3.方法区
- 也属于jdk (堆),不连续的,静态的
- 是一种java虚拟机的规范。(静态方法区:放一些不变的)
(模板、不动的)
运行时常量池:
直接内存:可以直接去交互的内存块。
4.JVM回收垃圾
垃圾回收机制 GC:(garbege collection)
- 自动回收(new的),回收没用的,赋值null即可。
垃圾回收算法:
①引用计数法:减减,至0时,回收。
循环引用的无用对象无法识别。
②引用可达法(根搜索算法):
找根,再找有应用到的节点,剩下的就是没有用过的节点,被GC掉。
5.分代垃圾回收机制:
①年轻代 Eden、Survivor(很少用的)
- Minor GC:Eden(一起用完才清空);
Survivor1,2(没请掉的到这里来);
再清,清了15次还没清掉,丢到年老代去。
②年老代Tenured/Old(经常用的)
- Major GC年老代;
Full GC:全量回收,大扫除,全面清除掉所有我能控制的区域(年轻+年老)
③永久代(一直在用的)
与JVM共存亡。
- JVM调优,很大部分对于Full GC,
System.gc():“建议”启动垃圾回收,而不是调用运行。
但是大部分都会接受建议。
6.this 、static关键字
- this:创建好的对象的地址。
a.this的常用用法:
-
产生了变量名字重名的歧义,可以用this表示当前对象。
普通方法中,this指向调用该方法的对象;
构造方法中,this指向正要初始化的对象。 -
this关键字调用重载构造方法时,避免相同的初始化了。
但只能在构造方法中用,并且位于构造方法的第一句。 -
this 不能用于static方法中。
b.static关键字:
- 静态初始: 代码块前面加 static
在静态初始化块中,不能直接访问非static成员
7.变量的分类
1.局部变量
方法或语句块内部声明;属于方法/语句块:从该方法开始,到这块执行完,变量消失。
2.成员变量(实例变量)
类内部,或者方法的外部声明;属于对象。对象创建,变量创建,随对象的消失变量一起消失。
3. 静态变量
在类内部声明,用static修饰;属于类。类被加载,静态变量就有效,随编译器的启动而启动,关闭而消失。所有都可以访问。
8.包机制
- package:相当于文件夹
开源的,起名有要求:用域名作用的名字。(域名倒着写)com.yuming.test… - com.yuming和com.yuming.com区别:逻辑上有父子关系但是实际上是两个完全独立的个体。
JDK中的主要包
核心包
1.java.lang:**String**、Math、Interger、System、Thread提供常用功能
(这个核心包可以不用导入就使用)
2.java.awt:集成窗口工具集的多个类,构造管理应用程序图形用户界面(GUI)(少用的)
3.java.net:执行类与网络相关的操作类
4.java.io:提供多功能输入/输出类
5.java.util:包含一些实用的工具类,如定义系统特性、使用与日期日历相关的类
import导入新的包♥
-
import . com. yuming .包名.*;
不存在先后顺序。 -
具体到导入某一个类:全部写进去;
-
外面的其他包我都想要:不用具体到class,用 .* 表示;(会降低编译速度,不会降低运行速度)
··· -
Alt+Enter可以快捷键自动导入。
五、继承 extend
- 私有属性(变量),共有方法(类),get、set方法获取。
- get、set驼峰命名规则:alt+shift+insert自动生成
意义:
- 提高程序的安全性,保护数据
- 隐藏细节
- 统一接口
- 提高系统的可维护性。(修改内部代码)
1.单继承
类与类的关系:
- 类只有单继承:只有一个直接的父类
- 接口有多继承
- 继承的实现:代码的复用
可以继承属性和方法。(扩展extends)
class xxx extends yyy{
}
-
公共的public才可以继承,私有的不可以继承。
-
public、protected、default、private优先级依次往后。
-
虽然可以继承所有属性和方法(父类构造法除外),但不一定所有的都可以直接访问(如私有属性)
2.组合
收购了,并购了。
this.person.name = dog;
3.继承和组合
都可以实现代码的复用。
- 继承:is - a的关系
- 组合:has-a的关系
(逻辑上的关系注意一下)
六、override 重写
-
覆盖
-
子类重新定义父类。(父类的引用指向了子类)√
父类B 变量b 指向= 引用new子类 A();
(方法的调用只和左边的有关)
1.重写的特点:
- 是父类和子类才有的(存在继承关系)。是子类重写父类的方法。
- 方法名必须相同。
- 参数列表必须相同。(否则是重载了)
重载是名字或者参数列表有不一样。 - 修饰符:范围可以扩大,不能缩小:public最大,protected,default、private最小。
(子类可以访问的范围更大,优于父类) - 抛出异常:异常的范围可以被缩小, 但不能扩大。(继承之后一定变好了,不能越来越差了)
重写子类和父类的方法必须一致,方法体不同。
即符合:
①“= =”:方法名、形参列表相同
②”≥“:访问权限,子类大于等于父类
③“≤”:返回值类型和声明异常类型,子类小于等于父类。
2.重写的原因:
-
父类的功能:子类不是所有的都需要,也不是都满足需要。
ALT+shift+INSERT : override
3.final关键字
- 修饰变量:被它修饰的变量不可改变。不可以重新被赋值。
final int MAX_SPEED = 120;
- 修饰方法:方法不能被重写,我的方法不可以被子类重新修改,但是可以被重载。(可以随便用,不可以改)
final void study(){
}
- 修饰类:修饰的类不可以被继承(不需要子类了)。如Math、String。
final class A{
}
4.object类:
- 是所有java的父类(根)
- 也就是:所有的除了构造类的都能被继承,但是不一定都能用。(如私有的就不能使用)
public class Person{
...
}//等价于以下:
public class Person extends Object{
...
}
- object类包括:
hashCode();toString(); clone();getClass();notify(); wait(); equals();等…
1.toString方法
-
可以自动调用返回值为String类型的方法;
-
s.toString(); 直接输出时,括号里面可以不写。
-
可以重写toString。
-
toString()方法默认返回的字符串是: 对象+@+地址。
2.==号与equals方法
public boolean equals(Object obj){
return (this == obj);
}
是否与当前的hashcode一样。(两个对象是否相同)
3.super
- 可以看作时直接父类对象的引用。可以用来访问父类中被子类覆盖的方法和属性。
- super的注意点:
- 所有的构造方法第一句总是super(…)或者this(…)。因此,自己不调用时,系统会自动调用无参的super();构造器。
- super调用父类的构造方法,必须在子类构造器的第一行
- super 必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法!(因为super 和this 调用都得在第一行)
- super 和 this区别:
-
代表的对象不同
this:本身调用者这个对象
super:代表直接父类对象的应用
前提: -
this:没有继承也可以使用(可以直接使用,默认的)
super:只能在继承条件下可以使用 -
构造方法:
this(); 当前本类的构造
super();直接父类的构造
七、封装encapsulated
- 实现高内聚,低耦合。(封装类的内部细节,便于修改内部代码,而不许外部干涉,提高可维护性;简化外部调用,便于调用者使用,便于扩展和协作。)
1.访问控制符
- 从而实现封装
1.private
私有,只有同一个类可以访问。
2.default
没有修饰符修饰,只有同一个package的类可以访问。(一个包中多个类都可以访问)
3.protected
可以被同一个包的类以及其他包中的子类访问。(同类+同一个包的不同类+不同包的子类)
注意:♥
- 父类和子类在同一个包中时,子类可以访问父类的protected成员,也可以访问父类对象的protected成员。
- 父类和子类不在同一个包中时,子类可以访问父类的protected成员,但是不能访问 父类对象的protected成员。
4.public
所有类都可以使用,只要是这个project就可以使用。
2.封装的使用细节
简单规则:
- 属性:一般使用private访问权限
- 属性私有后,提供相应的get/set方法来访问相关属性,这些方法通常是public修饰。(Boolean 变量的get方法是is开头的)
- 方法:一些只用于本类的辅助性方法可以用private修饰。
有需要其他类调用的方法用public修饰。
八、多态polymorphism
-
是方法的多态:同一个方法的调用,对象的不同行为引起的。= =重写 override(方法体)
-
一个类的实际对象是确定的,但是可以指向这个对象的 引用类型是任意的:他的本类、父类、祖宗object等等都可以引用同一个类。
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
- 右边的为实际对象。能执行的方法组要看左边的类型,和右边关系不大。左边有才可以用。
1.对象的转型
case转
-
而父类是不可以调用子类后面的私有方法。
-
高转低的话,可以强制类型转化。
- 多态的注意:
- 多态是方法的概念,属性没有多态。(override的本质)
- 父类与子类之间继承关系时,才可以强制类型转换。
不相关无联系的类时如果强制转化:异常报错:ClassCastException! - 存在的条件:
①是继承关系,
②方法需要重写。
③父类的引用指向子类对象。Father f1 =指向 new son();
- 不可以被重写的:
- static
- final
- private
也就不存在多态。
2.抽象方法和抽象类
-
抽象方法:就是一种声明;
使用abstract修饰;
没有方法体。
具体实现是通过子类提供的具体方法实现的。 -
抽象类:abstract定义的规范。抽象方法没有确定的。包含抽象方法的就是抽象类。
- 抽象类的使用要点
- 是个规范,但是不一定每个人都可以做到。
- 有抽象方法的类只能定义成抽象类;
- 抽象类不能实例化,即不能new一个;
- 抽象类包含属性、方法、构造方法。但是构造方法不能用来new实例;
- 抽象类只能用来被继承;
- 抽象方法必须被子类实现。
3.接口(interface)
只有抽象方法和常量。
- 接口 : 契约(本质:还是抽象类)…如果是xxx,则你必须实现…
- 只有规范,只有方法的类型。自己无法写方法:是专业的约束。
- 是规范(方法声明)与实现的分离。
- 区别♥
- 普通类:具体实现
- 抽象类:具体实现+规范(抽象的方法)
- 接口:规范
- 接口的作用:
- 接口是约束。
- 实现类可以实现多个接口,也就是接口可以实现多继承
- 定义一些方法,让不同的人实现,接口一样,实现的方式不一样。
- 方法:所有的类型都是public abstract类型的类。
- 静态 常量(属性): public static final
- 调用:直接void(do);
- 接口不能实例化,因为接口中不可以构造方法。
- 可以实现多个接口:通过implements
- 实现接口中的类之后,必须重写接口中的方法。
- 接口的使用
- 默认public abstract void xxx();抽象方法;
- 默认public static final类型的常量;
- 接口可以多继承;
- 接口的默认方法和静态方法
- 也被称为是扩展方法。
- default关键字表示默认方法。
- 所有这个接口的实现的类都会继承这个方法。
- 从属于接口(一种特殊的类)。
- 默认方法是静态的。
- 接口的多继承
可以有多个父类:可以继承与多个父类。必须实现所有的方法。
4.instanceof 运算符
用来判断一个对象是什么类型:判断两个关系是否存在父子继承关系。
A instanceof B:
能不能编译通过,取决于A与B之间是否存在继承关系。
三条关系线:
Object>Person>Student
Object>Person>Teacher
Object>String
1 Object s1 = new Student();
System.out.println(s1 instanceof Student); //true
System.out.println(s1 instanceof Person); //true
System.out.println(s1 instanceof Object); //true
System.out.println(s1 instanceof Teacher); //false
System.out.println(s1 instanceof String); //false
所以,s1,与teacher、string不在同一棵树上。
2 Person s2 = new Student();
System.out.println(s2 instanceof Student); //true
System.out.println(s2 instanceof Teacher); //false
System.out.println(s2 instanceof Object); //true
// System.out.println(s2 instanceof String); 直接编译报错,直接不同路线。
System.out.println(s2 instanceof Person); //true
k
3 Student s3 = new Student();
System.out.println(s3 instanceof Student); //true
// System.out.println(s3 instanceof Teacher); 直接编译报错,同级不同路线
System.out.println(s3 instanceof Object); //true
// System.out.println(s3 instanceof String); 直接编译报错,直接不同路线。
System.out.println(s3 instanceof Person); //true
- 类型之间的转换(非基本类型)
- 强制类型转换(会丢失方法)= = = 高(父)- - - > 低(子)
- 向上转型:不用强制转换,添加方法等
- 方便方法的调用,减少重复代码。
5.常用类
-
包装类
八大基本类型都有:自动装箱和拆箱。(因为需要面向对象) -
枚举类:
最基本的用法掌握即可:
定义: enum 枚举名字{
枚举体(简单的列表常量)最后一个末尾可以不写分号
}
遇到复杂的东西时候,直接创建一个其他类即可。
创建枚举类型:
enum Season{
SPRING,SUMMER,AUTUMN,WINTER
}
System.out.println(Season.SUMMER);
遍历输出:
for(Season k : Season.values()){
System.out.print(k+"t");
}
switch与枚举:
int a = new Random().nextInt(4);//生成0,1,2,3四个随机数。
switch(Season.values()[a]){
case SPRING:
System.out.println("春天");
break;
case SUMMER:
System.out.println("夏天");
break;
case AUTUMN:
System.out.println("秋天");
break;
case WINTER:
System.out.println("冬天");
break;
}
九、异常:Exception
Process finished with exit code 1
后面是1,表示存在异常;后面是0表示正常退出。- 出现异常的时候,程序可以安全退出, 处理完之后继续执行。
用户输入的问题、不存在的问题、内存不够的问题…
- 被除数为0:ArithmeticException:运算条件异常
- 检查型异常:用户错误或问题引起的异常,程序员无法预见的。
- 运行时异常:写的时候不报错,运行时可以在编译时忽略。
- 错误:非异常。栈溢出等。如无限循环:StackOverflowError
异常的分类:
Throwable类、Exception、Error(jvm出错,重启。。)
Exception:
- RuntimeException(UncheckedException)运行时异常,编译器不知道,编译的时候不会报错;
- CheckedException:编译时的异常,编译时候就通过不了
异常类结构层次图:
异常的处理
1.抛出+捕获异常:
处理异常的五个关键字:try、catch、finally、throw、throws
快捷键:自动包裹代码捕获异常:选中当前代码+Ctrl+Alt+T:try/catch/finally
- 分成三块:try+catch+finally。可以使用多个catch: 但是假设要捕获多个异常,异常必须从小到大捕获。Throwable、其次Exception,最小error,最先写error。
try{
//想要捕获的异常类型
System.out.println(a/b);//语句1
System.out.println(c/d);//语句2
}catch (Error e){
//catch 捕获异常(先小后大)
System.out.println("Error");
}catch (Exception e){
System.out.println("Exception");
}catch (Throwable e){
System.out.println("Throwable");
}
finally {
//善后工作(不管有无处理异常,都正常输出)
System.out.println("finally");
}
//finally 可以不要,用于:假设IO资源关闭,就会用到。try、catch 一定要。操作系统的资源也得关闭。
注意: 1.catch后面的语句如果是由父子关系的时候,先写子类,后写父类。没有父子关系可以不管先后。
2.语句1出现的异常,往后解决之后,不会再返回语句2.
2.声明异常
- 谁调我谁处理。(推迟处理 )
Throw:手动抛出异常,在方法中使用
public void test(int a,int b){
if (b==0){
throw new ArithmeticException(); //主动抛出异常,方法中使用
}
- Throws:假设这方法中,处理报不了这个异常。方法上抛出异常
public static void main(String[] args) {
try { //用了try、catch捕获异常之后,程序继续往下执行,如有异常,直接此处结束
new Test().test(1,0 ); //匿名内部类
} catch (Exception e) {
e.printStackTrace();
}
}
//假设这方法中,处理报不了这个异常。就在方法上抛出异常
public void test (int a,int b) throws ArithmeticException{ //方法上抛出异常
if (b==0){
throw new ArithmeticException();
//方法中主动抛出异常
}
}
- ♥ throw 和 throws的区别:几乎没有相同的地方。
throw:生成一个异常对象,并手动抛出,在方法内部;
throws:自动、在方法声明的末尾处,抛出异常(处理异常的方式)。先存在异常,“上有排污,下游治污”。
3.try-with-resource自动关闭
本质上还是try-catch-finally。
自动关闭资源。
try(****);{ }
自动实现了AutoClosable的接口。
可不用finally。jvm跑的还是try-catch-finally。
4.自定义异常:
-
进入可能会存在异常的方法
-
传递参数a
-
判断是否要抛出异常,无则继续输出
-
对这个方法的参数进行调用,捕获自定义的MyException异常
-
打印异常的消息(自定的MyException异常里的toString();)
(规划一整套异常体系比较难)
处理异常的思路
- 细心看异常信息,确定异常种类、相关代码行(独立解决50+);
- 确定上下文相关的关键词信息(疑难问题,需要);
- 拷贝异常信息百度10篇以上,查看相关帖子,找思路(搜具体名词、再减少关键词放宽条件)(用空格代替标点符号);
- 前两步不会再向同级请教;
- 前三步无法解决,请教领导。
- 总结:
常见的RuntimeException异常:自己要解决的
- ArithmeticException
逻辑上的不严密造成的,比如除数为0;这种情况下要加以控制语句if何时可行条件,修改。 - NullPointerException
空指针异常:对象(变量在栈中)是空的时候,调用了他的方法(此时堆中是没有的)。
解决方法:加以判断if(变量!= null);
- ClassCastException
不可以转换的类型:if(a instanceof b){ }
来判断一下是不是同一个类型的,是的话可以强制转换,不是就不转了。 - ArrayIndexOutOfBoundsException
数组越界了:范围之外(数组)
解决方法:加以判断if(a>0&&a<arr.length){ }
- NumberFormatException
数字格式化异常:引入正则表达式判断是否为数字。
CheckedException异常:
- 创建的时候异常:可以检查出来的。
实际应用中的经验总结:
1 . 处理运行异常时,采用逻辑去合理规避同时辅助try-catch处理
2. 在多重catch块后面,可以加上一个catch(Exception)来处理可能会被遗漏的异常。
3. 对于不确定的代码,也可以加上try-catch,处理潜在的异常
4. 尽量去处理异常,切记不要只是简单的调用printStackTrace()去打印输出,在printStackTrace()前面,增加一些处理异常的代码块(把我们的损失降到最低)
5. 具体如何处理异常,要根据不同的业务需求和异常类型去决定
6. 尽量添加finally语句块去释放占用的资源:IO流、Scanner等
最后
以上就是秀丽马里奥最近收集整理的关于Java面向对象基础篇一、面向对象OO:(类+对象)==表格二、类三.对象object,instance四、面向对象的内存分析 ♥五、继承 extend六、override 重写七、封装encapsulated八、多态polymorphism九、异常:Exception的全部内容,更多相关Java面向对象基础篇一、面向对象OO:(类+对象)==表格二、类三.对象object,instance四、面向对象的内存分析内容请搜索靠谱客的其他文章。
发表评论 取消回复