Java是一门面向对象的语言
面向对象分析 OOA
面向对象设计 OOD
面向对象编程 OOP
实体:看得见摸得着的物体 对生活中的实体进行分类
对象
类和对象的关系:
1.类是对象的模板,对象是类的实例
2.一个类可以创建N个对象
3.每个对象都是独一无二的
4.对象和类满足is a的关系
类:
是我们在生活中对身边的事务进行不自觉的分类!在脑海中只是一个定义,生活中不存在,存在的是具体的实例
对象:
用来描述事物的一个实体,由一组属性和方法构成
把一组具有相同属性和行为的一些对象,封装成一个类
面向对象的优势:
1.与我们的思维方式一致
2.提高程序的可重用性
3.隐藏对象的内部细节,提高程序的维护性和安全性
直接写在类中的属性
局部变量没有默认值,不赋予初始值不能直接使用
所有的访问权限修饰符:
1.public 公共的,级别最宽松
2.protected 受保护的,只能在子类中访问
3.default 默认的访问权限,没有这个单词,仅限于本包中访问
4.private 私有的,级别最严的,只能本类中访问
访问权限修饰符可以定义在全局变量和方法上
步骤:
1.创建对象 实例化对象
类名 对象名=new 类名();//实例化一个对象,调用无参构造
只要有(),就说明是一个方法
类名()----构造方法,
只有构造方法才能构造出一个类的实例
例: new Student();
通过构造方法来创建类的实例
疑问 在Student类中并没有Student()方法,系统会默认给我们创建类的无参 构造方法
2.使用对象的属性和方法
对象名.属性名
对象名.方法名
Java中没有指针的概念,示意图中的箭头只是一种比喻,在Java中指针我们称之为引用
null是所有引用类型的默认值,不能点出来任何内容,只要点出来,就会出现 NullPointException(空指针异常)
调用对象某个方法的时候,给方法的东西叫参数
调用对象的某个方法,返回的东西就是返回值
无参构造:
访问修饰符+类名===构造方法 用来创建对象的实例
绝对不允许加返回值
new 类名();//实例化一个对象,调用无参构造
带参构造:
目的:在创建对象的同时,给对象的各个属性赋值
(int age,String name)参数列表
1.int age,String name形参
2.必须有数据类型
3.实参的参数列表和顺序必须和形参一致
this:当前对象
this.age=age;将用户传递过来的局部变量赋值给成员变量
在成员变量和局部变量同名的时候,使用this来区分
项目代码,阅读顺序
1.bean
2.test
3.login
4.demo
5.paramater
参数的传递
1.基本数据类型+String,作为参数传递,传递的都是值
2.引用数据类型,作为参数传递,传递的内存地址 (数组属于引用数据类型)
对象数组:
对象类型的数组
public class Student {
static Scanner input=new Scanner(System.in);
//int age;
String name;
//创建Student类型的数组
Student[] stu=new Student[5];
/**
* 定义一个方法,给数组中的每个对象的属性赋值
*/
public void addStudent(){
for (int i = 0; i < stu.length; i++) {
//实例化数组中的每个元素
stu[i]=new Student();
System.out.println("请输入第"+(i+1)+"个学生的姓名:");
stu[i].name=input.next();
//System.out.println("请输入第"+(i+1)+"个学生的年龄:");
//stu[i].age=input.nextInt();
}
}
/**
* 遍历对象数组中的每个对象的数据
*/
public void showStudent(){
System.out.println("****学生信息如下****");
for (Student s : stu) {
System.out.println(s.name);
}
}
/**
* 修改学生姓名
*/
public void changeName(String oldName,String newName){
boolean flag=false;
for (int i = 0; i < stu.length; i++) {
if(stu[i].name.equals(oldName)){
stu[i].name=newName;
flag=true;
break;
}
}
if(flag){
System.out.println("找到了!");
}else{
System.out.println("没找到!");
}
}
/**
* 查找学生姓名
*/
public void findName(int start,int end,String name){
boolean flag=false;
for (int i = start-1; i < end; i++) {
if(stu[i].name.equals(name)){
flag=true;
break;
}
}
if(flag){
System.out.println("找到了!");
}else{
System.out.println("没找到!");
}
}
public static void main(String[] args) {
//实例化对象
Student student=new Student();
student.addStudent();
//修改学生姓名
System.out.println("请输入您要修改的学生姓名:");
String oldName=input.next();
System.out.println("请输入修改后的学生姓名:");
String newName=input.next();
student.changeName(oldName, newName);
System.out.println("请输入您要查找的初始位置:");
int start=input.nextInt();
System.out.println("请输入您要查找的结束位置:");
int end=input.nextInt();
System.out.println("请输入您要查找的学生姓名:");
String name=input.next();
student.findName(start, end, name);
student.showStudent();
}
}
shift+alt+s ---overrite implements method--object--toString()
1.因为Java中所有的类都继承object
2.如果我们想输出对象,不是看它的内存地址,而是需要看到对象的每个属性值
3.需要重新object类中的toString()
shift+alt+a:全选
面向对象的三大特性:
1.封装
概念:将类的所有信息隐藏起来,不让外部类直接访问,而是通过对应的方法去访问
目的:隐藏类的内部细节,安全
步骤:
1.所有属性私有化
2.创建对应的get set方法shift+alt+s
3.在set方法中增加逻辑判断,确保数据的准确性
所有的get都是取值,所有的set都是给属性赋值
方法重载:方法=行为 其实就是一个静态的多态
1.在同一个类中
2.方法名相同
3.参数列表不同(个数||类型||顺序)
4.与访问修饰符和返回值无关
static:
一个类在被JVM加载的时候,首先会加载类中被static修饰的所有属性,方法,代码块.并把这个static修饰的内容放进静态存储区,便于我们共享访问
static修饰的属性和方法叫做类属性和类方法,其他的叫做实例属性和实例方法
1.static可以修饰
1.属性 静态属性
2.方法 静态方法
3.代码块 静态代码块
2.static的特点
01.static修饰的内容,在整个程序运行期间,只有一份,而且所有对象共享
比如说,我们在Student中定义了一个变量,
static int age;
Student类中创建N个对象,都共享这个 age属性
如果有一个对象更改了age属性的值,其他的N个对象也跟着变化
02.静态方法中不能访问非静态属性和静态方法
int age;//普通属性
public static void sayHello(){
System.out.println(age);//编译报错
}
03.普通的方法中可以访问静态属性和静态方法
static int age;//静态属性
public void sayHello(){
System.out.println(age);
}
04.静态属性和静态方法可以直接通过类名访问
类名.静态属性
类名.静态方法
比如说:Student类有一个普通方法sayHello(){}
我们想调用这个方法?
1.实例化对象 Student s=new Student();
2.调用方法 s.sayHello();
现在sayHello()变成了静态方法,我们怎么访问?
1.sayHello()在Student类中,我们无需实例化
2.直接访问Student.sayHello()
书写实体类的步骤:
1.私有化属性
2.快捷键生成set,get方法
3.快捷键生成有参和无参构造
4.重写toString()
this注意点:
1.this()调用无参构造
2.this(……)调用带参构造
3.this调用构造方法时,只能出现在构造方法中
4.this调用构造方法时,必须位于构造方法中的第一行
5.this访问对象的属性或者方法的时候,可以出现在任何方法中
2.继承(extends)
Object是所有java类的父类
super()调用父类的无参构造,无论有没有显式调用父类的无参构造,都会调用父类 的无参构造,如果没有调用父类的带参构造,会先执行父类的无参构造,再执行子类 的带参构造
注意:
(1.如果我们实例化子类对象的时候,调用的是无参构造,会先调用父类的无参构造
2.如果我们实例化子类对象的时候,调用的是带参构造,但是在构造方法中没有显 式的输出super(参数),默认会先调用父类的无参构造
3.如果我们实例化子类对象的时候,调用的是带参构造,在构造方法中显式的输出 super(参数),默认会先调用父类的带参构造)
1.无论子类是否显示的调用super,都会先调用父类的无参构造,除非显示调用父类 的带参构造
2.父类中私有的属性或者方法,子类不能继承
3.父类的构造方法,子类也不能继承
super关键字:
1.只能出现在子类的方法中
2.如果调用父类的构造方法,只能出现在子类的第一句
3.super.属性 调用父类的属性
super.方法 调用父类的方法
重写的注意事项:
1.有继承关系
2.不在一个类中,子类重写父类的方法
3.方法名一致,参数列表一致
4.重写方法的访问权限修饰符不能严于父类
5.父类中的静态方法不允许被重写,子类中可以创建同名的静态方法,跟父类的 无关
6.父类的私有方法不允许被重写
7.如果父类的方法有返回值,子类重写的时候,可以返回这个值的本身或者是返 回值的子类型
子类和父类满足is a的关系
单根性:一个类只能有一个直接的父类
equals:
(基本数据类型比较的是值,引用数据类型比较的是内存地址)
1.为什么String类中的equals是比较的字符串内容
01.查询Object类中的方法
public boolean equals(Object obj) {
return (this == obj);
}//比较的是内存地址
02.再去看String类中的方法
String中的equals是重写了Object类中的equals方法,比较的是内 容
String a="abc";
String b="abc";
String c = new String("abc");
System.out.println(a.equals(b)); // 值肯定一致 所以返回 true
System.out.println(a == b);// 内存地址也一致 所以 true
System.out.println("****************************************");
System.out.println(a.equals(c));// 值肯定一致 所有返回 true
System.out.println(a == c);// 内存地址不一致 所以 false
String a = "a";
String b = "bc";
String c = "abc";
System.out.println(c == ("a" + "bc")); //true
01.在程序编译期间 会把常量(不变)a 和常量bc 合并成 abc
02.之后再和“abc“进行比较
String a = "a";
String b = "bc";
String c = "abc";
System.out.println(c == (a + b)); // false
01. a 和 b 都是变量(变化), 在编译期间无法确定变量的值
02. c在编译期间已经确定, ab无法确定
final String a = "a";
final String b = "bc";
String c = "abc";
System.out.println(c == (a + b)); // true
final可以修饰:
1.修饰的属性,就是常量,运行期间不能改变
2.修饰的方法,不能被子类重写
3.修饰的类不允许被继承
例子:
1.如果 Student类和Teacher类都没有去重写父类的sleep方法,name调用sleep 方法的时候,都是输出同样的语句
2.让子类去重写父类的sleep方法(子类一旦重写了这个sleep方法,当前父类 的这个方法有存在的意义,但是方法中的内容<方法体>没有存在的意义!因为 Person的子类会去重写这个方法
01.去掉方法体之后发现编译错误,
02.鼠标放在错误位置出现两种选择
001.add body X
002.add abstract √
03.在方法上面增加了abstract 之后,还是报错,鼠标放在错误位置,出现两 种选择
001.remove abstract X
002.make type Person abstract √
)
abstract: 一个方法的声明处出现了abstract关键字----抽象方法
1.抽象方法必须位于抽象类中
2.抽象方法没有方法体
3.必须被子类重写,除非子类也是抽象类
抽象类
1.抽象类可以有普通方法
2.抽象类不能被实例化,但是可以有构造方法
3.多态
之前的练习中,使用过方法重载
方法名一致,代表的是同一个行为
参数列表不一致,代表的是行为所需要的参数不一致
结果也不一样
程序中的多态
1.静态的多态 方法重载(程序在编译期间,就已经确定了需要执行的方法)
2.动态的多态 程序在运行期间才能确定需要执行什么方法
同一个引用类型(父类),使用不同的对象实例(子类),执行一个相同的操作, 但是得到不同的结果
多态存在的必要条件
1.要有继承
2.要有重写
3.向上转型 父类引用指向子类对象(指针泛化)
多态的实际应用:
1.使用父类作为方法的参数
2.使用父类作为方法的返回值
接口
案例:1.小猫小狗都有一个共同的属性
2.提取一个Animal类
3.小猫小狗等其他动物都有吃饭的方法
4.所有在Animal类定义一个eat()方法
5.每个动物吃的食物不同,所以Animal的eat()方法不能有方法体
6.Animal变成了抽象了
加了一个动物----小鸟
7.小鸟会飞
8.如果把fly()放进Animal里面,不可行,所有的动物都会飞了
9.航天器,飞机……等都会飞
10.如果我们在每个类中都去书写fly()方法,也不行
has a>------>>实现implements接口Interface)
class
superclass
abstract
interface
接口的特点:
1.所有的方法都是抽象方法,不允许有普通方法
2.接口的方法必须被实现类实现,除非实现类是抽象类或者接口
3.接口中所有的变量都是静态常量,必须赋予初始值(Ctrl+shift+x/y 大小写)
4.接口解决了Java中单根继承的问题,一个类可以实现N个接口
5.类继承父类,实现接口,
一个接口可以继承N个接口
6.接口也不允许被实例化,也不允许有构造方法
接口的类型:
1.大多都是方法
2.大多都是属性
3.什么也没有
内部类:每个内部类都会单独生成一个.class文件
把一个类写在了另外一个类或者方法中
外部类必须是public修饰的,不能更改访问权限修饰符,内部类可以设置访问权限修饰符
内部类的分类:
1.成员内部类
使用成员内部类:
1.实例化外部类对象
2.通过外部类对象创建内部类对象
3.调用内部类的属性和方法
Father father=new Father();
Father.Son son=father.new Son();
son.sayHello();
特点:
1.可以拥有private,protect访问权限修饰符
2.如果外部类和内部类属性重名,默认使用内部类
想使用外部类的属性 外部类名.this.属性/方法名
"外部类的age"+Father.this.age
3.想访问内部类,必须先创建外部类对象
2.局部内部类
1.仅限于方法体内使用(局部变量)
3.匿名内部类
1.没有名称,看不到类的定义
2.所有的匿名内部类必须继承一个类或者实现一个接口
3.如果匿名内部类中需要外部的参数,这个参数必须是final修饰
4.静态内部类
1.成员内部类加上static
2.不依赖于外部类,可以直接创建对象
/**
* 访问静态内部类
*/
Son2 son2=new Son2();
son2.sayHello();
3.不能访问外部类非静态的属性和方法
异常:
程序在运行期间发生了不可预测的事件,阻止了程序的正常运行
异常的处理机制:在我们程序发生异常之后,代码能够按照我们事先设计的顺序 继续执行!
异常的分类:
所有异常和错误的父类------>>Throwable
1.运行时异常 RunTimeException
ArithmeticException 算术异常
ArrayIndexOutOfBoundsException 数组下标越界
NullPointerException 空指针异常
InputMisMatchException 数据类型不匹配
ClassCastException 对象强制类型转换
NumberFormatException 数字格式转换异常
2.受查异常 CheckedException IOException
异常的使用
try catch finally throw throws
异常的处理分为两种方法
1.try catch finally
try
01.不能单独使用,必须和catch /finally连用
02.代码块中存放可能出现异常的代码
03.如果try代码块中出现了异常,会去匹配catch代码块对应的异常类型,没有匹 配的类型的时候,直接进入finally
catch
01.可以有多个catch块,每个catch都能捕获一个异常
02.多个catch块捕获的异常类型不允许重复
03.多个catch块的异常类型必须是从小到大排列
04.如果多个catch块都能匹配,默认使用第一个匹配的
05.如果try中都没有发生异常,catch代码块被忽略
06.每个代码块中的变量都是私有的
finally
01.无论异常是否发生,代码块都会执行
02.如果遇到了System.exit(0);或者System.exit(非0),不会执行finally代码块
03.如果try代码块出现了return,先执行finally再跳出方法
04.后续关闭流,释放数据库链接资源
2.throw抛出异常 throws声明异常
throw抛出异常
01.语法throw new 异常类型(异常信息)
02.异常类型必须是Exception或者其子类
03.一个throw只能抛出一个异常
04.throw只能出现在方法体内
05针对于抛出的异常,有两种方式解决
001.try catch finally
002.throws
06.抛出异常的类型必须是声明异常类型本身或者是其子类类型
throws声明异常
01.语法 throws 异常类型1,异常类型2……
02.定义在方法的参数列表之后,可以声明多个异常
03.throws不是处理异常,是声明异常,方法的调用者去处理异常
04.如果在main方法中使用throws,则是jvm来处理异常
异常链的使用:
把我们捕获的异常包装成一个新的异常,继续抛出,新异常中记录了异常的原始信息
便于找到异常的根本原因
// main方法
public static void main(String[] args) {
try {
firstException();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 第1个异常
private static void firstException() throws SQLException {
try {
secondException();
} catch (IOException e) {
e.printStackTrace();
throw new SQLException("第1个异常", e);
}
}
// 第2个异常
private static void secondException() throws IOException {
try {
thirdException();
} catch (InputMismatchException e) {
e.printStackTrace();
throw new IOException("第2个异常", e);
}
}
// 第3个异常
private static void thirdException() throws InputMismatchException {
throw new InputMismatchException("根本的异常");
}自定义异常:
1.异常类必须是Throwable的子类
2.自定义异常类继承RuntimeException,Exception
/**
* 针对于Student的异常类
*/
public class StudentException extends Exception { public StudentException(String msg) {
super(msg);
} public StudentException(String msg, Throwable e) {
super(msg, e);
} }
/**
* 针对于AgeException的异常类
*/ public class AgeException extends StudentException {
public AgeException() {
super("年龄异常");
} }
/**
* 针对于NameException的异常类
*/ public class NameException extends StudentException {
public NameException() {
super("姓名异常");
} }
/**
* StudentDemo测试类
*/ public class StudentDemo {
public static void main(String[] args) throws StudentException {
Scanner input = new Scanner(System.in);
System.out.println("请输入异常(age/name)");
String answer = input.next();
if (answer.equals("age")) {
throw new AgeException();
} else if (answer.equals("name")) {
throw new NameException();
} else {
createStudent();
} }
private static void createStudent() throws StudentException {
throw new StudentException("学生创建异常");
}}