Java学习笔记(三)Java面向对象编程 -- 详细的Java基础教程系列

Java 面向对象编程(OOP)

人类思想的方法原则的高深体现:抽象,分类,继承,聚合,多态

基于java尚硅谷教程的学习笔记,以及自己的一些理解和新知识分享

一、前言

(一)面向对象的三大特征

  • 封装
  • 继承
  • 多态

(二)面向对象核心思想

  • Object–对象和Class–类是面向对象的核心概念

  • Class–类是一类事物的抽象定义

  • Object–对象是实际存在的该类事物的个体,是类的实例化

  • 万事万物皆对象

二、Class–类

  • Class中的Member(成员)

    • 属性(Field) = 成员变量
    • 方法(Method) = 函数/成员方法
  • 类的语法格式

    修饰符 class 类名{
        属性声明;
        方法声明;
    }
    
    修饰符:缺省,public,private(这个私有类定义只能是内部或者嵌套类)
    
  • 类的访问机制

    • 一个类中的访问机制:类中方法直接访问类中成员变量(例外:static方法访问非static,编译不通过)
    • 不同类中访问机制:先创建对象,再用对象访问类中定义的成员

三、Object对象

(一)使用对象

Person p1 = new Person();
Person p2 = new Person();

image-20210320095857522

(二) 对象的生命周期

image-20210325083457406

(三)对象内存解析

image-20210320100213089

堆(Heap):存放对象实例和数组

栈(Stack):存储局部变量,对象引用(对象在堆内的首地址),方法执行完自动释放

方法区(Method Area):用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

(四)对象内存细致解析

image-20210320100841277

(五)匿名对象

  • 不定义对象的句柄,直接调用对象的方法
    • new person().shout();
  • 使用情况
    • 一个对象只需要进行一次方法调用
    • 将匿名对象作为实参传递给一个方法调用(工程思想)

二、类的成员

(一)属性Field

  • 语法格式

    修饰符 数据类型 属性名 = 初始化值;
    
    -修饰符:private,缺省,protected,public,static,final
    -数据类型:基本数据类型+引用数据类型
    -属性名:标识符,符合命名规范即可
    
    public class Person{
    	private int age;
    	public String name = "CalvinHaynes"
    }
    
    
  • 变量分类

    • 成员变量(方法体外,类体内)–有默认初始化值
      • 实例变量(非static)
      • 类变量(static)
    • 局部变量(方法体内)–必须显示初始化
      • 形参(方法、构造器中定义的变量)
      • 方法内局部变量
      • 代码块内局部变量
  • 成员变量和局部变量的区别

    image-20210320101640370

  • 属性的默认初始化赋值

    image-20210320101803130

(二)方法Method

对象所能实现的功能封装,便于简化代码,实现代码复用

1、 声明格式
修饰符 返回值类型 方法名(形参列表){
    方法体
	return 返回值;
}

修饰符:publicprivateprotected,缺省
返回值类型:void(无返回值),其他数据类型
2、方法分类

image-20210320102212218

3、调用方法时的内存调度

image-20210320102258351

注意事项:方法中只能调用方法或者属性,不可在方法内部定义方法

4、方法重载(overload)
  • 同一类中,允许存在一个以上的同名方法,只要参数类型或参数个数不同即可

  • 确定指定的方法:先看方法名,再看参数列表

  • 判断是否是重载,只与方法参数个数和类型的不同有关,与方法的权限修饰符,返回值类型,形参变量名,方法体都没有关系

    public void man(int age){
        
    }
    
    public void man(String name,int age){
        
    }
    
    public void man(){
        
    }
    
5、可变个数的形参
  • 声明格式:方法名(参数类型名 …参数名)
  • 方法参数部分指定类型的参数个数是可变多个,可以传入任意数量参数
  • 可变参数方法使用和方法参数部分使用数组是一样的
  • 可变个数形参的方法与同名方法也构成重载
  • 方法的参数中如果有可变个数形参一定要放在最后面(认真思考一下,如果可变个数形参放在参数列表的第一个或中间会出现什么效果)
  • 在一个方法的形参位置,最多只能声明一个可变个数形参
public void test(String ...books){
    
}

public void test(String[] args){
    
}

public void test(String book){
    
}

public void test(int num,String name,String ...books){
    
}
6、方法参数的值传递机制
  • 方法参数
    • 形参:声明时的餐宿
    • 实参:实际传给形参的值
  • Java参数的值如何传入方法呢?
    • 参数传递方式只有一种:值传递
    • 值传递的分类
      • 形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
      • 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
7、两道有趣的题目
1、貌似是考察方法的参数传递

image-20210325092625061

//方法一
public static void method(int i,int j) {
    i = 100;
    j = 200;

    System.out.println("a = " + i + " b = " + j);

    System.exit(0);
}
2、微软面试题

image-20210325094601918

//误区:从头到尾遍历,第一个除完第一个第一个值变为1了
//错误写法
for(int i = 0li < arr.length;i++){
    arr[i] = arr[i] / arr[0];
}

//最简便写法,从后向前遍历
for(int i = arr.length - 1;i >= 0;i--){
    arr[i] = arr[i] / arr[0];
}

//另一种写法
int temp = arr[0];
for(int i = 0;i < arr.length;i++){
    arr[i] = arr[i] / arr[0];
}
8、递归方法(recursion)
  • 递归:自己调用自己(方法体内调用方法本身)
  • 递归是一种隐式循环的实现,重复执行代码但是不需要循环控制流程结构
  • 递归的注意事项
    • 一定要向已知方向递归
    • 一定要有结束条件

三、面向对象特征:封装和隐藏

防止使用者对类中成员的直接操作导致数据错误、混乱、安全性泄露或程序错误执行

(一)思想

  • 通过定义访问权限来封装和隐藏信息
    • 隐藏属性(private):隐藏类中无需对外的技术细节(其实也是公司企业的一种知识产权的表现,同时防止误操作属性使得整个程序运行异常)
    • 封装方法:使用者只能通过事先定义好的方法来访问数据(这样设置的好处是方便加入控制逻辑,限制对属性的不合理操作)
    • 便于修改,增强可维护性

(二)四种访问权限修饰符

image-20210325095647645

注意:对于class的权限修饰只可以用public和default(缺省)

  • public类可以在任意地方被访问
  • default类只可以被同一个包内部的类访问
class Animal{
    private int legs;
    
    public void setLegs(int i){
        if(i != 0 && i != 2 && i != 4){
            System.out.println("wrong number of legs!");
            return;
        }
        legs = i;
    }
    
    public int getLegs(){
        return legs;
    }
    
    public class Zoo{
        public static void main(String[] args){
            Animal xb = new Animal();
            xb.setLegs(4);
            System.out.println(xb.getLegs());
        }
    }
}

四、构造器(3W法讲解)

(一)what?

  • 构造器是与类相同名称的一个构造方法

(二)why?

  • 为了创造对象时初始化成员属性(new对象时)
  • java在创建对象时,会在使用对象之前调用相应的构造器,确保每次对象都能够正确初始化(是C语言每次都要调用初始化函数的升级版,也是防止程序员忘记初始化的一个很牛皮的语法)

(三)how?

  • 语法格式
修饰符 类名(参数列表){
	初始化语句;
}


//示例
public class Person{
    
    private int age;
    
    public Person(){
        age = ;
    }
    
    public Person(int age){//构造器重载
        this.age = age;
    }
    
    public int getAge(){
        return age;
    }
    
    public void setAge(int age){
        this.age = age;
    }
}
  • 分类

    • 隐式无参构造器(系统默认)–未定义构造器时,其实系统默认就已经有一个无参构造器了
    • 显示定义一个或多个构造器(无参、有参)
  • 注意:

    • java中,每个类至少有一个构造器
    • 默认构造器修饰符与所属类的修饰符一样
    • 一旦显式定义了构造器,系统不再提供默认构造器
    • 一个类可以创建多个重载构造器
    • 父类的构造器不可以被子类继承

JavaBean:Java语言写成的可重用组件

  • 类是公共的
  • 属性是private的
  • 有对应的public的get、set方法

关于JavaBean,之后了解深刻之后单独出一篇博客

五、关键字this(3W)

(一) what?

  • 顾名思义,this即代表了当前“这个”东西,有点抽象,接着往下看

(二)why?

  • 在方法内部使用时,可以用this引用该方法所属类
  • 在构造器内部使用,this表示该构造器正在初始化的东西

(三)how?

  • 在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性。不过,通常我们都习惯省略this。

  • 当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this来表明该变量是类的成员变量

  • 使用this访问属性和方法时,如果在本类中未找到,会从父类中查找

  • this可以作为一个类中构造器相互调用的特殊格式

class Cat{
	private String name;
	private int age;
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public int getAge() {
		return age;
	}
	
	public Cat() {
		String info = "Cat初始化时,需要考虑如下的1,2,3,4...共40行代码";
		System.out.println(info);
	}
	
	public Cat(String name) {
		this();
		this.name = name;
	}
	
	public Cat(int age) {
		this();
		this.age = age;
	}
	
	public Cat(String name,int age) {
		this(age);
		this.name = name;
	}
}

六、关键字:package、import

(一)package

1、what and how?
  • package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包。(若缺省该语句,则指定为无名包)。它的格式为:
    package 顶层包名.子包名子包名 ;

  • 包对应于文件系统的目录,package语句中,用语句中,用 “.” 来指明包来指明包(目录目录)的层次;

  • 包通常用小写小写单词标识。通常使用所在公司域名的倒置:com.atguigu.xxx

2、why?
  • 包帮助管理大型软件系统:将功能相近的类划分到同一个包中。比如:MVC的设计模式(以后会单独出blog)
  • 包可以包含类和子包,划分项目层次,便于管理
  • 解决类命名冲突的问题
  • 控制访问权限

(二)import

  1. 在源文件中使用import显式的导入指定包下的类或接口
  2. 声明在包的声明和类的声明之间。
  3. 如果需要导入多个类或接口,那么就并列显式多个import语句即可
  4. 举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
  5. 如果导入的类或接口是java.lang包(java language,默认全局包)下的,或者是当前包下的,则可以省略此import语句。
  6. 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的
    是哪个类。
  7. 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
  8. import static组合的使用:调用指定类或接口下的静态的属性或方法

个人博客地址:CalvinHaynes’s Blog

初来乍到,请多多指教

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值