java基础知识笔记_面向对象

1.形式参数的问题

基本类型:形式参数的改变不影响实际参数
引用类型:形式参数的改变直接影响实际参数

如果一个方法的形式参数是一个类类型(引用类型),这里需要的是该类的对象

2.匿名对象

匿名对象就是在栈内存中没有指针指向堆内存中new出来的对象

  • 匿名对象的应用场景:
    调用方法,仅仅只调用一次,注意,调用多次的时候不合适
  • 匿名对象有什么好处?
    匿名对象调用完就是垃圾,可以被垃圾回收器回收
  • 匿名对象可以作为实际参数传递

3.封装的概述

定义一个学生类:
成员变量:name,age
成员方法:show()方法

我们在使用这个案例的过程中,发现了一个问题:
通过对象去给成员变量赋值,可以赋值一些非法的数据。这是不合理的。应该是这个样子的:在赋值之前,先对数据进行判断。

	判断到底在哪里做比较合适呢?
	StudentDemo类是一个测试类,测试类一般只创建对象,调用方法。所以,这个判断应该定义在Student类中。
	
	而我们在成员变量的位置可不可以进行数据判断呢?
	是不可以的,因为做数据校验,必须要依靠一些逻辑语句。逻辑语句是应该定义在方法中的,所以,我们最终决定在Student类中提供一个方法来对数据进行校验。
	
按照我们前面的分析,我们给出了一个方法进行校验。但是呢,它偏偏不调用方法来赋值,还是直接赋值了,这样我们的方法就没有起到作用。我就应该要求你必须使用我的方法,而不能直接调用成员变量赋值。怎么去强制要求不能直接使用成员变量呢?针对这种情况,Java就提供了一个关键字 private
  • private:私有的。可以修饰成员变量和成员方法。
    注意:被private修饰的成员只能在本类中访问。

其实我讲到现在讲解的是一个封装的思想。封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

封装的好处

  • 隐藏实现细节,提供公共的访问方式
  • 提高代码复用性,提高安全性

4.private

是一个权限修饰符
可以修饰成员变量和成员方法
被其修饰的成员只能在本类中被访问(后面有详解)

5.this关键字

this代表当前类的对象引用,就表示当前类的一个对象,注意:谁调用这个类,在该方法内部的this就代表谁

this的场景:解决局部变量成员隐藏成员变量

this关键字内存图解
在这里插入图片描述

6.构造方法

给对象的数据进行初始化

  • 格式:

    • 方法名与类名相同
    • 没有返回值类型,连void也没有
    • 没有具体的返回值
  • 注意事项:

      如果我们没有给出构造方法,系统将自动提供一个无参构造方法
      如果我们给出了构造方法,系统将不再提供默认的无参构造方法
      注意:这个时候,如果我们还想使用无参构造方法,就必须自己给,建议自己给出无参构造
    
  • 给成员变量赋值有两种方式:

    1. setXxx()
    2. 构造方法

7.static关键字

针对多个对象有共同的这样的成员变量值的时候,java提供了一个关键字static

  • static的特点:(它可以修饰成员变量,还可以修饰成员方法)
    • 随着类的加载而加载

    • 回想main方法。优先于对象存在

    • 被类的所有对象共享

        举例:咱们班级的学生应该共用同一个班级编号。其实这个特点也是在告诉我们什么时候使用静态?如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
        举例:
        	饮水机(用静态修饰)
        	水杯(不能用静态修饰)
      
    • 可以通过类名调用
      其实它本身也可以通过对象名调用。推荐使用类名调用。

静态修饰的内容一般我们称其为:与类相关的,类成员

static关键字注意事项:
在静态方法中是没有this关键字的
	如何理解?
		静态是随着类的加载而加载,this是随着对象的创建而存在的
		静态比对象先存在
			
静态方法只能访问静态的成员变量和静态的成员方法
	静态方法:
		成员变量:只能访问静态变量
		成员方法:只能访问静态成员方法

	非静态方法:
		成员变量:可以是静态的,也可以是非静态的
		成员方法:可以是非静态的成员方法,也可以是静态的成员方法

		静态只能访问静态

静态成员变量内存图
在这里插入图片描述

8.main方法的格式:

public static void main(String [] args){…}

  • public:公共的,访问权限最大。被jvm调用
  • static:静态的,不用创建对象,通过类名就可以使用,方便jvm调用
  • void:返回给jvm内容没有意义
  • main:是一个常用的方法入口,很多语言都是以main作为入口
  • String[] args:字符串数组,早期是为了接收键盘录入的数据的
  • 格式:java MainDemo hello world java

9.math类的学习

Math:类包含于执行基本数学运算的方法由于Math类在java.long包下,所以不需要导包

特点:没有构造方法,因为它的成员全部是静态的

获取随机数方法:public static double random():返回带正号的double值,该值大于等于0.0且小于1.0

10.代码块

在Java中,使用{}括起来的代码被称为代码块根据其位置和声明的不同,可以分为

  • 局部代码块:局部位置,用于限定变量的声明周期

  • 构造代码块:在类中成员的位置,每次调用构造方法执行之前,都会先执行构造代码块
    作用:可以把多个构造方法中的共同代码放到一块,对对象进行初始化

  • 静态代码块:在类中的成员位置
    作用:一般是对类进行初始化

11.代码块面试题

静态代码块,构造代码块,构造方法的执行顺序
静态代码块 > 构造代码块 > 构造方法
静态代码块:只执行一次
构造代码块:每次调用构造方法都执行

class Student {
static {
System.out.println("Student 静态代码块");
}

{
System.out.println("Student 构造代码块");
}

public Student() {
System.out.println("Student 构造方法");
}
}

class StudentDemo {
static {
System.out.println("hhh");
}

public static void main(String[] args) {
System.out.println("我是main方法");

Student s1 = new Student();
Student s2 = new Student();
}
}

/*执行结果:
hhh
我是main方法
Student 静态代码块
我是main方法
Student 构造代码块
Student 构造方法
Student 构造代码块
Student 构造方法*/

12.继承

  • 继承的概念:把多个类中相同的内容给提取出来定义到一个类中

  • 继承的格式:class 子类 extends 父类{}

  • 继承的好处

    • 提高了代码的复用性
    • 提高了代码的维护性
    • 让类与类之间产生了关系,是多态的前提
  • 继承的弊端:类的耦合性增强了

      开发的原则:低耦合,高内聚
      耦合:类与类的关系
      内聚:就是自己完成某件事情的能力
    
  • java中继承的特点

    • java只支持单继承,不支持多继承
      有些语言是支持多继承,格式:extends 类1,类2…

    • java支持多层继承(继承体系)

        继承的注意事项:
        1.子类只能继承父类所有非私有的成员(成员变量和成员方法)
        2.子类不能继承父类的构造方法,但是可以通过super关键字访问父类构造方法
        3.不要为了部分功能去继承
      
  • 继承中成员变量的关系:(采用就近原则)

    • 子类中的成员变量和父类中的成员变量名称不一样
    • 子类中的成员变量和父类中的成员变量名称一样
  • this和super的区别

      	this代表本类对应的引用
      	super代表父类存储空间的标识(也可以理解为父类引用,可以操作父类的成员变量)
      	怎么用?
      		调用成员变量
      			this.成员变量 调用本类成员变量
      			super.成员变量 调用父类成员变量
      		调用构造方法
      			this()调用本类构造方法
      			super()调用父类构造方法
      		调用成员方法
      			this.成员方法 调用本类成员方法
      			super.成员方法 调用父类成员方法
    
  • 继承中构造方法的关系

      子类中所有的构造方法默认都会访问父亲中空参数的构造方法,因为子类会继承父类中的数据,可能还会使用父类中的数据,所以,子类初始化之前,一定要完成父类数据的初始化
      子类每一个构造方法的第一句默认都是:super()
      如果父类没有无参构造(有带参构造),子类的构造方法会出现什么呢?
      报错,如何解决
      	1.在父类中加一个无参构造方法
      	2.通过使用super关键字去显示的调用父亲的带参构造方法
      	3.子类通过this去调用本类的其他构造方法
      		子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化
      注意事项:
      	this(...)或者super(...)必须出现在第一条语句上
      	如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上
    

13.继承中的面试题:

class Fu{
	public int num = 10;
	public Fu(){
		System.out.println("fu");
	}
}
class Zi extends Fu{
	public int num = 20;
	public Zi(){
		System.out.println("zi");
	}
	public void show(){
		int num = 30;
		System.out.println(num); 
		System.out.println(this.num); 
		System.out.println(super.num); 
	}
}
class ExtendsTest {
	public static void main(String[] args) {
		Zi z = new Zi();
		z.show();
	}
}

/*执行结果:
	fu
	zi
	30
	20
	10
	*/
class Fu {
	static {
		System.out.println("静态代码块Fu");
	}

	{
		System.out.println("构造代码块Fu");
	}

	public Fu() {
		System.out.println("构造方法Fu");
	}
}

class Zi extends Fu {
	static {
		System.out.println("静态代码块Zi");
	}

	{
		System.out.println("构造代码块Zi");
	}

	public Zi() {
		System.out.println("构造方法Zi");
	}
}

class ExtendsTest2 {
	public static void main(String[] args) {
		Zi z = new Zi();
	}
}

/*执行结果:
	静态代码块fu
	静态代码块zi
	构造代码块fu
	构造方法fu
	构造代码块zi
	构造方法zi
	*/
/*一个类的初始化过程
		成员变量初始化
		默认初始化
		显示初始化
		构造方法初始化
*/

/*子父类的初始化(分层初始化)
先进行父类初始化,然后进行子类初始化*/
	class X {
		Y b = new Y();
		X() {
			System.out.print("X");
		}
	}
	
	class Y {
		Y() {
			System.out.print("Y");
		}
	}
	
	public class Z extends X {
		Y y = new Y();
		Z() {
			//super
			System.out.print("Z");
		}
		public static void main(String[] args) {
			new Z(); 
		}
	}
	
	执行结果:
		Y
		X
		Y
		Z

14.方法重写

  • 方法重写:子类中出现了和父类中声明一摸一样的方法

  • 方法重载:本类中出现了方法名一样,参数列表不同的方法。与返回值无关

  • 方法重写的应用:沿袭了父类功能,又定义了自己特有的内容

      方法重写的注意事项
      1.父类中私有的方法不能被重写
      	因为父类私有方法子类根本就无法继承
      2.子类重写父类方法时,权限不能更低
      	最好一致
      3.父类静态方法,子类也必须通过静态方法进行重写
      	其实这个算不上方法重写,但现象确实如此
    

    面试题:

      1:方法重写和方法重载的区别?方法重载能改变返回值类型吗?
      
      方法重写:
      	在子类中,出现和父类中一模一样的方法声明的现象。	
      方法重载:
      	同一个类中,出现的方法名相同,参数列表不同的现象。
      
      方法重载能改变返回值类型,因为它和返回值类型无关。
      
      Override:方法重写
      Overload:方法重载
    
    
      2:this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
      	
      this:代表当前类的对象引用
      super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)
      
      场景:
      	成员变量:
      		this.成员变量
      		super.成员变量
      	构造方法:
      		this(...)
      		super(...)
      	成员方法:
      		this.成员方法
      		super.成员方法
    

14.final关键字的引入

由于继承中有一个现象:方法重写有时候,我们不想让子类覆盖掉父类的功能,这个时候java提供了一个关键字:final

  • final:最终的意思。常见的是它可以修饰类,方法,变量。

  • final的特点

    • final可以修饰类,该类不能被继承
    • final可以修饰方法,改方法不能被重写(覆盖,重写)
    • final可以修饰变量,该变量不能被重新赋值。因为这个变量其实是常量
  • 常量的定义

    • 1.字面值常量
      “hello”,10,true

    • 2.自定义常量
      final int x = 10;

        面试题:final修饰局部变量的问题
        基本类型:基本类型的值不能发生改变
        引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的
      
  • final修饰变量的初始化时机
    1.被final修饰的变量只能赋值一次
    2.在构造方法完毕前(非静态)

15.多态

多态:同一个对象,在不同时刻体现出来的不同状态

  • 多态的前提

    • 要有继承关系
    • 要有方法重写
    • 要有父类引用指向子类对象
      父 f = new 子();
  • 多态中的成员访问特点

    • 成员变量
      编译看左边,运行看左边
    • 构造方法
      创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化
    • 成员方法
      编译看左边,运行看右边
    • 静态方法
      编译看左边,运行看左边
      (静态和类相关,算不上重写,所以访问还是左边的)
  • 多态的好处

    • 提高了代码的维护性(继承保证)
    • 提高了代码的扩展性(由多态保证)
  • 多态的弊端
    不能使用子类的特有功能
    如果想使用子类特有功能,怎么用呢?

    • 创建子类对象调用方法即可(可以,但是很多时候不合理,而且占内存)

    • 把父类的引用强制转换为子类的引用(向下转型)

      对象间的转型问题:
      向上转型
      	Fu f = new Zi();
      向下转型
      	Zi z = (Zi)f;//要求该f必须是能够转换为Zi的
      

多态内存图解:
在这里插入图片描述
多态中对象变化内存图
在这里插入图片描述

	classCastException:类型转换异常
	一般在多态的向下转型中容易出现

16.抽象类

  • 抽象类的特点

    • 抽象类和抽象方法必须用abstract关键字修饰

    • 抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类

    • 抽象类不能实例化
      因为它不是具体的。
      抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?

    • 抽象的子类
      a:如果不想重写抽象方法,该子类是一个抽象类。
      b:重写所有的抽象方法,这个时候子类是一个具体的类。

      抽象类的实例化其实是靠具体的子类实现的。是多态的方式。
      
  • 抽象类的成员特点

    • 成员变量:既可以是变量,也可以是常量。
    • 构造方法:有。
      用于子类访问父类数据的初始化。
    • 成员方法:既可以是抽象的,也可以是非抽象的。
  • 抽象类的成员方法特性:
    A:抽象方法 强制要求子类做的事情。
    B:非抽象方法 子类继承的事情,提高代码复用性。

      一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
      A:可以。
      B:不让创建对象。
      
      abstract不能和哪些关键字共存?
      private	冲突
      final	冲突	
      static	无意义
    

17.接口

  • 接口的特点
    • 接口用关键字interface表示
      interface 接口名 {}
    • 类实现接口用implements表示
      class 类名 implements 接口名 {}
    • 接口不能实例化
      那么,接口如何实例化呢?
      按照多态的方式来实例化。
    • 接口的子类
      a:可以是抽象类。但是意义不大。
      b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)

由此可见:
A:具体类多态(几乎没有)
B:抽象类多态(常用)
C:接口多态(最常用)

  • 接口成员特点
    • 成员变量;只能是常量,并且是静态的。
      默认修饰符:public static final
      建议:自己手动给出。
      必须给变量初始化
    • 构造方法:接口没有构造方法。
    • 成员方法:只能是抽象方法。
      默认修饰符:public abstract
      建议:自己手动给出。

所有的类都默认继承自一个类:Object。
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。

	类与接口之间实现继承
	类与类:
		继承关系,只能单继承,可以多层继承。
	类与接口:
		实现关系,可以单实现,也可以多实现。
		并且还可以在继承一个类的同时实现多个接口。
	接口与接口:
		继承关系,可以单继承,也可以多继承。

	抽象类和接口的区别:
		A:成员区别
			抽象类:
				成员变量:可以变量,也可以常量
				构造方法:有
				成员方法:可以抽象,也可以非抽象
			接口:
				成员变量:只可以常量
				成员方法:只可以抽象
				
		B:关系区别
			类与类
				继承,单继承
			类与接口
				实现,单实现,多实现
			接口与接口
				继承,单继承,多继承
				
		C:设计理念区别
			抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
			接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。

18.四种权限修饰符

  • 修饰符
    权限修饰符:private,默认的,protected,public
    状态修饰符:static,final
    抽象修饰符:abstract


  • 权限修饰符:默认修饰符,public
    状态修饰符:final
    抽象修饰符:abstract
    用的最多的就是:public

  • 成员变量
    权限修饰符:private,默认的,protected,public
    状态修饰符:static,final
    用的最多的就是:private

  • 构造方法
    权限修饰符:private,默认的,protected,public
    用的最多的就是:public

  • 成员方法
    权限修饰符:private,默认的,protected,public
    状态修饰符:static,final
    抽象修饰符:abstract
    用的最多的就是:public

      除此以外的组合规则:
      成员变量:public static final
      成员方法:public static 
                public abstract
      		    public final
    
      权限修饰符:
      			本类	同一个包下(子类和无关类)	不同包下(子类)	不同包下(无关类)
      private 	Y		
      默认		Y		Y
      protected	Y		Y							Y
      public	Y		Y							Y				Y
    

19.内部类

把类定义在其他类的内部,这个类就被成为内部类

  • 内部类的访问特点:

    • 内部类可以直接访问外部类的成员,包括私有
    • 外部类要访问内部类的成员,必须创建对象
  • 内部类分类

    • 成员内部类
    • 局部内部类
  • 成员内部类

    • 如何直接访问内部类成员

    • 外部类.内部类名 对象名 = 外部类对象.内部类对象

        例:Outer.Inner oi = new Outer().new Inner();
      
  • 成员内部类的修饰符
    private 为了保证数据的安全性
    static 为了方便访问数据

      注意:静态内部类访问的外部类数据必须用静态修饰
    
  • 成员内部类被静态修饰后的访问方式是
    外部类名.内部类名 对象名 = new 外部类名.内部类名();
    Outer.Inner oi = new Outer.Inner();
    Outer.Inner.show();

      面试题:分别输出30 20 10通过外部类名限定this对象
    
class Outer{
		public int num = 10;
		class Inner{
			public int num = 20;
			public void show(){
				int num = 30;
				System.out.println(?); num
				System.out.println(??); this.num
				System.out.println(???); outer.this.num  new Outer().num
			}
		}
	}
  • 局部内部类的特点
    A:可以直接访问外部类的成员
    B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

      面试题:
      局部内部类访问局部变量的注意事项?
      A:局部内部类访问局部变量必须用final修饰
      B:为什么呢?
      	局部变量是随着方法的调用而调用,随着调用完毕而消失。
      	而堆内存的内容并不会立即消失。所以,我们加final修饰。
      	加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
      	我在内存中存储的是数据20,所以,我还是有数据在使用。
    

19.创建对像内存图解

一个对象内存图
在这里插入图片描述
两个对象内存图
在这里插入图片描述
三个对象内存图
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值