Java 面向对象 学习笔记
本学习笔记内容来自“【狂神说Java】Java零基础学习视频通俗易懂 ”,原视频链接:https://www.bilibili.com/video/BV12J41137hu
面向过程 & 面向对象
- 面向过程思想
- 步骤清晰简单,每一步完成什么操作
- 适用于处理简单问题
- 面向对象思想
- 分类的思维模式,分析整个系统
- 适合处理复杂问题
- 具体到微观操作,仍然需要面向过程的思路去处理
面向对象编程(Object-Oriented Programming,OOP)
-
本质
- 以类的方式组织代码
- 以对象的方式组织(封装)数据
-
抽象
-
三大特性
- 封装
- 继承
- 多态
方法
package OOP;
import java.io.IOException;
//Demo01 类
public class Demo01 {
//main 方法
public static void main(String[] args) {
System.out.println();
}
public String sayHello(){
return "hello,world";
}
//return 结束一个方法,返回值(可能为空)
public void hello(){
return;
}
public void readFile(String file) throws IOException{
}
}
静态方法和非静态方法
- 调用非静态方法,需要用实例化这个类 new
- 调用静态方法,直接用 类名.方法名
- 一个Java Class只能有一个public class,但能有多个class
package OOP;
public class Demo02 {
public static void main(String[] args) {
//调用非静态方法,需要实例化这个类 new
//对象类型 对象名 = 对象值;
Say say = new Say();
say.Hello();
//调用静态方法
//类名.方法名
Say.Hi();
}
}
package OOP;
//Say 类
public class Say {
//非静态方法
//只有类实例化之后才存在
public void Hello(){
System.out.println("Hello!");
}
//静态方法
public static void Hi(){
System.out.println("Hi!");
}
}
值传递和数值传递
- 值传递只传递数值,不会改变
- 引用传递传递的是对象引用地址
package OOP;
public class Demo03 {
public static void main(String[] args) {
//值传递
int a = 1;
change(a);
System.out.println(a);
//引用传递:对象,传递的是对象引用地址
Person person = new Person();
System.out.println(person.name);
change(person);
System.out.println(person.name);
}
//返回值为空
public static void change(int a){
a = 10;
}
public static void change(Person person){
person.name = "Bob";
}
}
//定义了一个Person类,有一个属性:name
class Person{
String name = "Alex";
}
类 & 对象
- 类是一种抽象数据类型,是对某一类食物整体描述/定义
- 对象是抽象概念的具体实例
- 类是对对象的抽象
创建和初始化对象
-
使用new关键字创建对象
-
使用new关键字创建时,除分配内存空间外,还会给创建好的对象进行默认初始化以及对类中构造器的调用
-
类中的构造器也称构造方法,是进行创建对象时必须调用的。构造器的特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
-
Alt + Insert自动生成构造器(可生成一个或多个)
-
静态方法区和类一起加载
package OOP.Demo04;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
}
}
/*
public static void main(String[] args) {
//类:抽象的,需要实例化
//类实例化后会返回一个自己的对象
//student对象就是一个Student类的具体实例
Student student1 = new Student();
Student student2 = new Student();
student1.name = "Alex";
System.out.println(student1.name);
student1.study();
student2.name = "Bob";
System.out.println(student2.name);
}
*/
/*
public static void main(String[] args) {
//new实例化了一个对象
Person person = new Person("Bob");
System.out.println(person.name);
}
构造器:
1.和类名相同
2.没有返回值
作用:
1.new本质在调用构造方法
2.初始化对象的值
注意:
1.一旦定义了有参构造,无参构造就必须显式定义
Alt + Insert
*/
封装
-
高内聚
- 类的内部数据操作细节自己完成,不允许外部干涉
-
低耦合
- 仅暴露少量的方法给外部使用
-
封装(数据的隐藏)
- 通常应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问
-
属性私有,get/set
package OOP.Demo05;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("Alex");
System.out.println(s1.getName());
s1.setAge(999);//不合法的
System.out.println(s1.getAge());
}
}
package OOP.Demo05;
public class Student {
//private: 私有
//属性私有
private String name;
private int id;
private char gender;
private int Age;
//提供可以操作这些私有属性的方法
//提供一些public的get、set方法
//get 获得这个数据
public String getName(){
return this.name;
}
//set 给这个数据设置值
public void setName(String name){
this.name = name;
//alt + Insert自动生成get/set
}
public int getAge() {
return Age;
}
public void setAge(int age) {
if (age<120 && age>0) {
this.Age = age;
}else{
this.Age = 3;
System.out.println("年龄错误!");
}
}
}
总结
-
- private用于表示私有属性
- private属性需要提供一些public的get和set方法
- 快捷键alt + Insert 快速生成getter和setter
- 封装可提高程序的安全性
继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
- extends:扩展。子类是父类的扩展
- JAVA中类只有单继承,没有多继承
- 子类继承父类后,会拥有父类的全部方法和属性
- Ctrl + H 打开继承关系树
- 在JAVA中,所有的类,默认继承Object
- 父类私有的东西子类不能访问
Super
-
注意点:
- super调用父类的构造方法,必须在构造方法的第一行
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
-
与this的区别:
-
代表的对象不同:
this:对象是调用者本身
super:对象是父类对象
-
前提
this:没有继承也可以使用
super:只能在继承条件下才可以使用
-
构造方法
this(); 本类的构造
super(); 父类的构造
方法重写
-
静态方法:方法的调用只和左边、定义的数据类型有关
-
非静态方法:重写
重写
-
需要有继承关系,子类重写父类的方法
-
1.方法名必须相同
-
2.参数列表必须相同
-
3.修饰符:范围可以扩大但不能缩小
-
public>Protected>Default>private
-
4.抛出的异常:范围可以被缩小,但不能扩大
- ClassNotFoundException --> Exception(大)
-
重写,子类的方法和父类必须一致,方法体不同
为什么需要重写
-
父类的功能,子类不一定需要,或者不一定满足
Alt + Insert;Override。
多态
- 动态编译:类型:可扩展性
- 即同一方法可以根据发送对象的不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多
- 多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
![]()
定义父类Person
public class Person {
public void say(){
System.out.println("parent");
}
}
定义子类Student继承Person
public class Student extends Person{
@Override
public void say() {
System.out.println("son");;
}
public void eat(){
System.out.println("eat");
}
}
测试类Application
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型不确定
//父类的引用指向子类
//Student能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//Person父类,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
s2.say();//子类重写了父类的方法,执行子类的方法
s1.say();
//s2.eat();//无法执行父类中没有的方法
((Student) s2).eat();//强制类型转换后可以执行
s1.eat();
}
}
/*
1.子类没有重写父类的方法,则调用父类的
2.子类重写了父类的方法,调用子类的
3.对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
*/
/*
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系。 类型转换异常 ClassCastException
3.存在条件:继承关系,方法需要重写,父类引用指向子类对象
4.不能重写的方法,没有多态:
(1)static 方法,属于类,不属于实例;
(2)final 常量;
(3)private 方法
*/
/*
//instanceof
Object obj1 = new Student();
//Object > Person > Student
//Object > Person > Teacher
//Object > String
System.out.println(obj1 instanceof Student);//true
System.out.println(obj1 instanceof Person);//true
System.out.println(obj1 instanceof Object);//true
System.out.println(obj1 instanceof Teacher);//false
System.out.println(obj1 instanceof String);//false
System.out.println("=======================");
Person per1 = new Student();
System.out.println(per1 instanceof Student);//true
System.out.println(per1 instanceof Person);//true
System.out.println(per1 instanceof Object);//true
System.out.println(per1 instanceof Teacher);//false
//System.out.println(per1 instanceof String);//编译报错
System.out.println("=======================");
Student stu1 = new Student();
System.out.println(stu1 instanceof Student);
System.out.println(stu1 instanceof Person);
System.out.println(stu1 instanceof Object);
//System.out.println(stu1 instanceof Teacher);//编译报错
//System.out.println(stu1 instanceof String);//编译报错
//System.out.println(X instanceof Y);//能不能编译通过,看X和Y有没有父子关系
//X instanceof Y:
//X是Y的子类时,输出值为true;
//X是Y的父类时,输出值为false
*/
Output:
son
son
eat
eat
Process finished with exit code 0
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系。 类型转换异常 ClassCastException
3.存在条件:继承关系,方法需要重写,父类引用指向子类对象
4.不能重写的方法,没有多态:
(1)static 方法,属于类,不属于实例;
(2)final 常量;
(3)private 方法
instanceof
- 引用类型,判断一个对象是什么类型
类型转换
- 子类转换为父类,可能丢失自己本来的一些方法
- 父类引用可以指向子类的对象
- 把子类转换为父类,向上转型
- 把父类转换为子类,向下转型;强制转换
- 方便方法的调用,减少重复代码
static
- 静态方法和属性和类一起加载到内存中,因此能直接调用
package OOP.Demo08;
//static
public class Student {
//2nd : 与对象同时产生,常用于赋初始值
{
//代码块(匿名代码块)
System.out.println("匿名代码块");
}
//1st : 只执行一次
static {
//没有名字,不能调用
//类一加载就执行,且永久只执行一次
//静态代码块(匿名代码块)
System.out.println("静态代码块");
}
//3rd
public Student(){
System.out.println("构造方法");
}
private static int age;//静态变量
private double score;//非静态变量
public static void main(String[] args) {
/*
Student s1 = new Student();
System.out.println(Student.age);
//System.out.println(Student.score);//非静态不能直接调用
System.out.println(s1.age);
System.out.println(s1.score);
*/
Student s1 = new Student();
System.out.println("============");
Student s2 = new Student();
}
}
Output:
静态代码块
匿名代码块
构造方法
============
匿名代码块
构造方法
Process finished with exit code 0
导入静态包:
package OOP.Demo08;
//用static静态导入包
//导入后方法可直接使用,而不必加包名前缀
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
抽象类
package OOP.Demo09;
//abstract 抽象类: 类 extends:单继承 (接口可以多继承)
public abstract class Action {
//由别的用户实现
//只有方法名字,没有方法的实现
public abstract void doSomething();
//1.不能new这个抽象类,只能靠子类去实现它
//2.抽象类中可以写普通的方法
//3.抽象方法必须在抽象类中
//抽象的抽象
}
package OOP.Demo09;
//继承了抽象类方法的子类,必须要有它的实现方法
//除非该子类也是抽象类方法
public abstract class A extends Action{
}
/*
public class A extends Action {
@Override
public void doSomething() {
}
}
*/
package OOP.Demo09;
public class Application {
public static void main(String[] args) {
//new Action();//编译错误,抽象类不能new
}
}
接口
-
接口就是规范,定义的是一组规则
-
对对象的抽象
-
约束和实现分离:面向接口编程
普通类、抽象类和接口
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范
接口的作用
- 约束
- 利用接口定义一些方法,让不同的人实现
- 接口中的方法都是public abstract
- 变量都是public static final (常量)
- 接口不能被实例化,接口中没有构造方法
- 类通过implements可以实现多个接口
- (接6)实现接口的类必须要重写接口中的方法
UserService:
//interface 定义的关键字,接口都需要有实现类
public interface UserService {
//常量(public static final)
int AGE = 99;
//接口中的所有定义都是抽象的 public abstract
void add(String name);
//public abstract void run();
void delete(String name);
void update(String name);
void query(String name);
}
TimeService:
public interface TimeService {
void timer();
}
UserServiceImplements:
//抽象类: extends
//类 可以实现接口 implements 接口
//实现接口的类,需要重写接口中的方法
//利用接口实现多继承
//利用 alt + Insert 可快速生成
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
内部类
-
内部类可以获得外部类的私有属性和方法
-
通过相应的外部类来实例化内部类
-
public class Outer { private int id = 10; public void out(){ System.out.println("外部类方法"); } public class Inner{ public void in(){ System.out.println("内部类方法"); } //内部类可以获得外部类的私有属性 public void getID(){ System.out.println(id); } //若Inner是静态类则获取不了id //因为静态类先于id被调入内存 } //局部内部类 public void method(){ class methodInner{ public void in(){ } } } } //一个java类中可有多个class //但只能有一个public class class A{ }
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中
new Apple().eat();
UserService userService1 = new UserService() {
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}


浙公网安备 33010602011771号