java基础

类: 描述事物的抽象体 (包含属性 + 行为)

对象是实例,栈 内存     堆内存--有默认值

基本类型默认0 引用类型是null  

方法上的是  形式参数,用于接收实际参数

堆内存的成员变量有默认值

栈内存的局部变量必须定义赋值,不给默认

成员局部,同名就近

new 就是堆里,开内存,建对象,初始化

成员变量和局部变量的区别
在类中的位置不同:成员变量 类中方法外,
  局部变量 方法内或者方法声明上;
在内存中的位置不同:
  成员变量 堆内存
  局部变量 栈内存
生命周期不同:
  成员变量 随着对象的存在而存在,随着对象的消失而消失
  局部变量 随着方法的调用而存在,随着方法的调用完毕而消失
初始化值不同:
  成员变量 有默认的初始化值
  局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。

 

 

基本类型作为形式参数:形参改变不影响实参

引用类型作为形式参数:影响

方法的形参是引用类型,其实需要的是该类型的对象,只有具体的对象才会调用功能,引用类型给地址值,地址值是new出来的.......java是值传递

 因为Java中对基本数据类型(如int、double、char等)进行传递时,实际上传递的是它们的副本,而不是原始变量本身。

对于对象(如类实例),虽然表面上看起来是传递了对象的引用,但实际上传递的是这个引用(即内存地址)的副本,而非对象本身。

这意味着在方法内部对对象状态的修改会影响到原始对象,但如果你试图重新赋值这个引用指向另一个对象,那么原始引用将不会改变。

参数传递机制被称为值传递(pass-by-value),这是 Java 中唯一的参数传递方式。无论传递的参数是基本数据类型还是对象引用,Java 都是通过复制变量的值来进行参数传递的。因此,Java 并不支持引用传递(pass-by-reference)。

值传递意味着当你调用一个方法时,方法参数接收到的是调用时传入的实际值的副本。换句话说,方法内操作的是值的拷贝,而不是原始值本身。因此,任何在方法内对参数进行的修改都不会影响到方法外的原始变量。

在 Java 中,即使传递的是对象,仍然是值传递。这里传递的是对象引用的值,即指向对象的内存地址的值。这意味着方法内对对象的引用本身的修改不会影响原始引用,但通过引用修改对象的内部状态会影响原始对象。

 

 

-- 封装--指隐藏对象的属性和实现细节,仅对外提供公共访问方式。将不需要对外提供的内容都隐藏起来。 把属性隐藏,提供公共方法对其访问

对象调用成员变量名是合法的。对象.成员变量------------------------但能乱赋值,赋值之前先判断------逻辑判断再方法种----get()  set()---不用set就用.成员变量咋整??  封装可以强制使用------private 修饰成员变量+方法---  只本类中访问 私有的

private  大多时候修饰变量,不修饰防范

 

setName  形参与成员变量同名---->>>就近原则>>自己给自己>>>>>> this  当前类的关键字--解决局部变量隐藏成员变量问题(就近原则导致)--方法被哪个对象调用,this就是谁,因为this在方法里面,谁调用方法   

类加载后及案例,方法区,供对象多次调用

 

构造方法--new 后的就是构造方法, 给对象的数据进行初始化,   给成员变量赋值 (set + 构造)

类组成:成变,构造,成员方法(有参无参有返无返)

XXX s = new XXX()

1加载Student.class文件进内存

2在栈内存为s开辟空间

3在堆内存为学生对象开辟空间

4对学生对象的成员变量进行默认初始化--第一次初始化

5对学生对象的成员变量进行显示初始化--第二次初始化(一般没有)

6通过构造方法对学生对象的成员变量赋值--第三次初始化

7学生对象初始化完毕,

8把对象地址赋值给s变量

 

 

类加载方法区,创建对象堆,方法调用即入栈

变量范围定义越小越好,方便回收

 

 

static----所有对象共享,一改都变--------静态区,随着类的加载而加载。

this 是对象,随着对象的创建而创建。静态没有this。

 

 main --- 静态方法 可以类名调用,main是虚拟机调用,不用创建对象

静态修饰的是类成员,非静态修饰的是对象成员

 

 

代码块 ---- 局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。

  1局部代码块  在方法中出现;限定变量生命周期,及早释放,提高内存利用率

  2构造代码块  在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行

  3静态代码块 在类中方法外出现,加了static修饰 在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且值执行一次。

 

继承 --使用父类的数据 ,父类一定要先初始化   所以 每一个构造方法的第一条语句默认都是:super()               特点 : 单 + 多层

  子类只能继承父类所有非私有的成员(成员方法和成员变量),私有的继承不了;子类调用父类公共方法,父类公共方法可以调用自己的私有变变量,子类直接调用父类私有变变量会报错
  其实这也体现了继承的另一个弊端:打破了父类的封装性; 
  子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。
  不要为了部分功能而去继承

在子类方法中访问一个变量 - 就近原则
首先在子类局部范围找,然后在子类成员范围找,最后在父类成员范围找(肯定不能访问到父类局部范围)
如果还是没有就报错。(不考虑父亲的父亲…)

super的用法和this很像
this代表本类对应的引用。
super代表父类存储空间的标识(可以理解为父类引用)

 

子类中所有的构造方法默认都会访问父类中空参数的构造方法
为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。
每一个构造方法的第一条语句默认都是:super() ,虽然子类中构造默认有super()。但初始化的时候,并不是按照这顺序执行,而是按照分层初始化执行,

成员变量初始化三步走--默认-显示--构造初始化,(基本变量 + 引用变量)

子父类初始化--分层初始化      子类构造的中默认第一行的 super() 仅仅表示要初始化父类数据,再初始化子类数据。

在子类方法中访问一个方法 - 就近原则  --- 方法重写(方法重载)

方法重写-- 方法里调用父类方法功能super.XXX(); 再加上自己业务逻辑 ,组合新方法--方法套方法; 若有static修饰保留传承,总体访问权限不能缩小

 

继承??? 不想被重写咋整??

final 终结者-final修饰变量的初始化时机,在对象构造完毕前即可

  修饰类,类不能被继承
  修饰变量,变量就变成了常量,基本类型的值只能被赋值一次, 引用类型的地址值不可变
  修饰方法,方法不能被重写

常量: 字面值 (固定值,无名称,不可修改)自定义(通过final关键字声明的有名称的不可变变量  final int a =10;)  

运行常量

final int RANDOM = new Random().nextInt();

final String TIME = LocalDateTime.now().toString();

 

多态 - 不同时刻表现出来的不同状态

  有继承或实现关系
  方法重写--让多态表现出来的不同状态
  有父类或父接口引用指向子类对象

成员变量-无重写
  编译看左边,运行看左边
成员方法- 有方法重写-故运行看右边
  编译看左边,运行看右边
静态方法(静态和类相关,算不上重写)- 不算重写
  编译看左边,运行看左边
所以前面我说静态方法不能算方法的重写

 

 

多态的好处  -- 多态利用抽象类和接口,将模块间依赖从具体实现转向抽象,降低耦合度。

提高了代码复用性
提高了程序的维护性(由继承保证) -- 创建新子类继承并实现方法-基于继承关系,只需要维护父类代码,提高了代码的复用性,降低了维护工作的工作量
提高了程序的扩展性(由多态保证) --- 工具类的方法参数,用父类接收--有新add的子类,不用变动
多态的弊端
  不能访问子类特有功能--编译不过  解决- 向下转型(强转)
那么我们如何才能访问子类的特有功能呢?
多态中的转型 --- 同一个对象

  向上转型 -从子到父 -父类引用指向子类对象  Fu f = new Zi();   上的成员变量,下的重写方法   -- 成员变量是对象的外在描述(父)  成员方法是对象的功能描述
  向下转型 -从父到子 -父类引用转为子类对象 Zi z = (Zi) f;  下的成员变量,下的独有方法 

 内存--堆有super区

编译时没有对象,只检查语法,运行时才有对象,会匹配-类型转换

.方法套方法,最后运行的是重写的方法

 

抽象类  - 在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。

不给直接  Animal a = new Animal(); (承上,强制避免直接new父类,多态的有力推广)

抽象类不能实例化, 编译报错抽象类不能实例化, 但有构造,构造作用? 用于子类访问父类数据初始化

那么,抽象类如何实例化呢?   --- 多态最主要的应用场景,不在具体类而在抽象类
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。 
抽象类的子类 要么是抽象类  要么重写抽象类中的所有抽象方法

抽象类的抽象方法:用于限定子类必须完成某些动作
抽象类的非抽象方法:用于提高代码的复用性

一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?  --可,强制使用子类实例化

abstract不能和哪些关键字共存

private 冲突  不能被继承
final 冲突 不能被改
static 无意义  abstract没有方法体 + static直接访问

 

接口 -- 扩展功能,为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现;

和抽象类一样,不调用,不实现。编译不会报错,但若要调用运行不报错,一定要有子类实现

具体类多态  - -抽象类多态 -- 接口多态         

接口不是类,是功能的扩展,不能实例化,那么,接口如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
接口的子类
  要么是抽象类
  要么重写接口中的所有抽象方法

成员变量只能是常量 (要求比抽象类更严),可以接口.常量。说明默认静态的。接口有默认修饰符 public static final
构造方法没有,因为接口主要是扩展功能的,而没有具体存在。子类构造里默认第一行的super()是Object
成员方法只能是抽象方法,默认修饰符 public abstract

抽象类 被继承体现的是:”is a”的关系。共性功能
接口 被实现体现的是:”like a”的关系。扩展功能

 

形式参数是
  基本类型
  引用类型(类,抽象类,接口)方法入参中, 类不能调用方法,所以要的是该类的对象,抽象类的子类对象,接口的实现类对象

备注:现有形参为抽象类,可编译通过且运行不报错,因为不能用也没调用,一调用就要自己补实现子类。(框架)
返回值类型是
  基本类型
  引用类型(类(匿名对象),抽象类,接口)   
链式编程 : 每次调用完,返回的是一个对象

 

public给所有,private只给本类,protected 只给子类用,,不论子类在哪。 默认只给同一包下不论是谁。

 

内部类  与外部类没有继承关系。  static可以修饰内部类,在方法位置上

成员内部类: 外部类名.内部类名 对象名 = 外部类对象.内部类对象;      但多 private修饰-数据安全,不给外面用。或static修饰-方便访问   外部类名.内部类名 对象名 = new  外部类.内部类();  -- static修饰可以类直接访问,但又是对象,所以new

      Outer.this.num

局部内部类

  成员方法里,在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

  

局部内部类访问局部变量的注意事项:
必须被final修饰? 为什么呢? 成员方法调用完会消失,局部变量也会消失,但局部内部类对象还在堆中没回收。
  因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。
  为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。通过反编译工具可以看一下。

匿名内部类- 局部内部类的简化写法 -- 匿名对象

  接口 i = new 类名或者接口名() {重写方法;}
  本质是一个继承了类或者实现了接口的子类匿名对象

 

10匿名内部类- lambda 表达式 - 方法引用

16泛型 - 集合+很多对象,向下转型出现转换异常--参考数组--参数化类型

一个泛型,很多应用适配,谁用谁改,我不用改。集合的add方法。

泛型推断

 类 接口  谁用谁变,提供者泛型约束

方法---  泛型不跟类走,那么返回值要 public <T> 返回类型 方法名(T),   任意类型

泛型通配

?不明确可任意类型

?extends E 向下限定 E及其子类

?super E 向上限定 E及其父类

泛型擦除 --反射

可变参数 --形参用无限数组接收

增强for 替代了迭代器(先判断后获取)

 

19异常

 

 编译期异常处理: 抛,try

调用的方法跟着编译期异常必须处理,调用的方法跟着运行时异常,可以不管。throw对象, 抛运行期-可以不管   但抛编译期异常-必须处理(否则编译不过)

 

--编译期间语法检查:成员变量,方法匹配,异常处理,泛型?

运行

 

23 多线程

24 设计模式

原则-单一,开闭(靠多态),里氏替换(靠多态),依赖注入(依赖抽象类不依实-面向接口抽象类编程),接口分离(多实现),迪米特(低耦合,接口编程)

  接口-工厂  简单工厂= 静态工厂 - 新增类,工厂要加if(单厂)    工厂方法,自己做实现抽象工厂类(多厂) 抽象工厂

  抽象类-模板

  多线程-单例

  装饰涉及-IO流

  适配器-GUI

 

26 网络编程

27枚举 反射 新特性

static final 常量选择器--枚举

枚举本质----多例----------常量对象-----常量名就是 new 的对象名, 类 春天= new 类(); 

继承Enum类(隐藏)---

枚举实现接口 -- 每个常量都要实现-- 匿名内部类

 

 

 

枚举与策略模式

JDK8新特性

函数式接口--接口只有一个抽象方法

 

注解

 标记注解 @Override

可在 编译,类加载,运行时 读取

框架 = 注解 + 反射 + 设计模式

a文档注解 
b编译时 有格式检查 (JDK内置3个注解)

c替代配置文件

反射可以获取注解。

自定义注解 必须配上注解的 信息处理流程(反射) 才有意义。

元注解-修饰其他注解的注解

image

最后加载到内存里,反射读取,XX.class.getAnnotations() 

 

image

 

image

image

 字节码实例

image

 

 

序列化

serialVersionUID什么时候出现?

答:在对象序列化到磁盘时,会根据当前类的结构生成serialVersionUID。

如果serialVersionUID由系统生成,可能导致在类更新后,反序列化失败,无法读取以往的版本。

所以一般情况下,我们会手动在类里面写一个固定的serialVersionUID值。

有什么作用?

答:用于反序列化时比对。反序列化时,先根据当前类的结构生成一个版本ID,和磁盘的版本ID进行比对,一致则反序列化成功,否则反序列化失败。

什么时候需要序列化和反序列化?

答:序列化:当想要把类信息写入磁盘时;反序列化:要从磁盘读取信息时;

Spring的特性IOC、AOP

  1. IOC:解耦
  2. AOP:业务增强

 

posted on 2025-02-16 22:54  daofree  阅读(6)  评论(0)    收藏  举报