Java基础(八 前面补充)
1、笔记
1、局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。 定义格式:
修饰符 class 外部类名称 {
修饰符 返回值类型 外部类方法名称(参数列表) {
class 局部内部类名称 {
// ...
}
}
} 小节一下类的权限修饰符:
public > protected > (default) > private
定义一个类的时候,权限修饰符规则:
1. 外部类:public / (default)
2. 成员内部类:public / protected / (default) / private
3. 局部内部类:什么都不能写 ---> 跟(default)不一样 2、局部内部类访问方法的局部变量
局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final的】。 备注:从Java 8+开始,只要局部变量事实不变,那么final关键字可以省略。 原因:
1. new出来的对象在堆内存当中。
2. 局部变量是跟着方法走的,在栈内存当中。
3. 方法运行结束之后,立刻出栈,局部变量就会立刻消失。
4. 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。 3、匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。 匿名内部类的定义格式:
(接口名称 对象名 = )new 接口名称() {
// 覆盖重写所有抽象方法
}; ---> ";"不可省略
对格式“new 接口名称() {...};”进行解析:
1. new代表创建对象的动作
2. 接口名称就是匿名内部类需要实现哪个接口
3. {...}这才是匿名内部类的内容 另外还要注意几点问题:
1. 匿名内部类,在【创建对象】的时候,只能使用唯一一次。 ---> 指每个方法只能使用一次
如果希望多次创建对象,而且类的内容一样的话,那么就需要使用单独定义的实现类了。
2. 匿名对象,在【调用方法】的时候,只能调用唯一一次。 ---> 类似只有一个方法的匿名内部类
如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
3. 匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
强调:匿名内部类和匿名对象不是一回事!!! 4、类(类比String)和接口都可以作为成员变量类型,标准写法就是把 实现类对象 传进去,同时接口还可以传进去 匿名内部类和匿名对象 5、接口可以作为方法的参数或返回值 6、静态内部类的访问
class Demo1_InnerClass {
public static void main(String[] args) {
//外部类名.内部类名 对象名 = 外部类名.内部类对象;
Outer.Inner oi = new Outer.Inner(); // new Outer.Inner() 相当于 Outer.new Inner(),new 是作用在Inner()上的(内部类对象)
oi.method();
//内部类里面静态方法的访问特点:外部类.内部类.静态方法名();
Outer.Inner2.print();
}
} class Outer {
static class Inner {
public void method() {
System.out.println("method");
}
} static class Inner2 {
// 静态内部类的静态方法的访问
public static void print() {
System.out.println("print");
}
}
} 7、局部内部类访问局部变量必须用final修饰
局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?
因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用 但是jdk1.8取消了这个事情,所以我认为这是个bug,虽然取消,如果在书写代码时候,没有手动添加,系统底层也会默给你final 8、匿名内部类【重点】 写在方法里面
* A:匿名内部类
* 就是内部类的简化写法。
* B:前提:存在一个类或者接口
* 这里的类可以是具体类也可以是抽象类。
* C:格式:
*
new 类名或者接口名(){
重写方法;
}
* D:本质是什么呢?
* 是一个继承了该类或者实现了该接口的子类匿名对象。 interface Inter {
public void print();
} class Outer {
class Inner implements Inter {
public void print() {
System.out.println("print");
}
} public void method(){
//Inner i = new Inner();
//i.print();
//new Inner().print();
//Inter i = new Inner(); //父类引用指向子类对象 new Inter() { //实现Inter接口
public void print() { //重写抽象方法
System.out.println("print");
}
}.print(); // 得到子类对象,直接调用print()
}
} interface Inter {
public void show1();
public void show2();
}
//匿名内部类只针对重写一个方法时候使用
class Outer {
public void method() {
// 方式一: 调用一次方法,重写一次接口方法 缺点: 麻烦
/*new Inter(){
public void show1() {
System.out.println("show1");
} public void show2() {
System.out.println("show2");
}
}.show1(); new Inter(){
public void show1() {
System.out.println("show1");
} public void show2() {
System.out.println("show2");
}
}.show2();*/ //方式二: 父类引用(Inter i)指向子类对象(new Inter()) 缺点: 不能写自己的方法
Inter i = new Inter(){
public void show1() {
System.out.println("show1");
} public void show2() {
System.out.println("show2");
} /*public void show3() {
System.out.println("show3");
}*/
}; i.show1();
i.show2();
//i.show3(); // 不能访问自己写的方法 //匿名内部类是不能向下转型的,因为没有子类类名
//总结: 匿名内部类只针对重写一个方法时候使用
}
} 9、匿名内部类在开发中的应用 //如何调用PersonDemo中的method方法呢?
//第一种方法
class Test1_NoNameInnerClass {
public static void main(String[] args) {
PersonDemo pd = new PersonDemo ();
pd.method(new Student());
} //这里写抽象类,接口都行
abstract class Person {
public abstract void show();
} class PersonDemo {
public void method(Person p) {
p.show();
}
} class Student extends Person {
public void show() {
System.out.println("show");
}
} //第二种方式 匿名内部类作为参数传递
class Test1_NoNameInnerClass {
public static void main(String[] args) {
PersonDemo pd = new PersonDemo();
//第二种方案 : 匿名内部类的用法:作为参数传递
pd.method(new Person(){
public void show() {
System.out.println("这是匿名内部类的show方法...");
}
});
}
}
//这里写抽象类,接口都行
abstract class Person {
public abstract void show();
} class PersonDemo { //当你看到一个方法的形式参数是一个类名的时候,这里其实需要的该类的对象
//补充: 当你看到一个方法的形式参数是一个抽象类类名或者是接口名的时候,这里其实需要的是该抽象类的子类对象或者该接口的实现类对象
public void method(Person p) {
p.show();
}
} 10、
A:代码块概述
在Java中,使用{}括起来的代码被称为代码块。
B:代码块分类
根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。
C:常见代码块的应用
a:局部代码块
在方法中出现;限定变量生命周期,及早释放,提高内存利用率
b:构造代码块 (初始化块)
在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
c:静态代码块
在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。
一般用于加载驱动 11、
在静态方法中是没有this关键字的 - 如何理解呢?
- 静态是随着类的加载而加载,this是随着对象的创建而存在。
- 静态比对象先存在。 12、
重写:子父类出现了一模一样的方法(注意:返回值类型可以是子父类)
class Demo4_Override {
public static void main(String[] args) { }
} class Person {
public void print() {
System.out.println("Person");
}
} class Student extends Person {
public void print() {
System.out.println("Student");
}
} class Father {
public Person method() {
return new Person();
}
} class Son extends Father {
public Student method() { //返回值类型可以是子父类
return new Student();
}
} 13、方法重写注意事项 - a:父类中私有方法不能被重写
- 因为父类私有方法子类根本就无法继承
- b:子类重写父类方法时,访问权限不能更低
- 最好就一致
- c:父类静态方法,子类也必须通过静态方法进行重写
- 其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解(静态只能覆盖静态)
- 子类重写父类方法的时候,最好声明一模一样。 14、
成员变量
- 编译看左边(父类),运行看左边(父类)。
成员方法
- 编译看左边(父类),运行看右边(子类)。
静态方法
- 编译看左边(父类),运行看左边(父类)。
- (静态和类相关,算不上重写,所以,访问还是左边的)
- 只有非静态的成员方法,编译看左边,运行看右边 15、
多态的好处
- a:提高了代码的维护性(继承保证)
- b:提高了代码的扩展性(由多态保证) (例子中参数只需 method(Animal a), 就可以接收 Cat c)
多态的弊端
- 不能使用子类的特有属性和行为。 16、接口成员特点
- 成员变量;只能是常量,并且是静态的并公共的。
- 默认修饰符:public static final
- 建议:自己手动给出。
- 构造方法:接口没有构造方法。
- 成员方法:只能是抽象方法。
- 默认修饰符:public abstract
- 建议:自己手动给出。 17、抽象类和接口的区别
A:成员区别
- 抽象类:
- 成员变量:可以变量,也可以常量
- 构造方法:有
- 成员方法:可以抽象,也可以非抽象
- 接口:
- 成员变量:只可以常量
- 成员方法:只可以抽象
B:关系区别
- - 类与类
- 继承,单继承
- 类与接口
- 实现,单实现,多实现
- 接口与接口
- 继承,单继承,多继承
C:设计理念区别
- 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
- 接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。 18、如何编译运行带包的类 - a:javac编译的时候带上-d即可(自动创建包名)
- javac -d . HelloWorld.java
- b:通过java命令执行。
- java 包名.HellWord 19、封装
隐藏实现细节,只提供接口访问。
封装是相对的。
Java基础(八 前面补充)的更多相关文章
- Java基础八--构造函数
Java基础八--构造函数 一.子父类中构造函数的特点 1.1 为什么在子类构造对象时,发现,访问子类构造函数时,父类也运行了呢? 原因是:在子类的构造函数中第一行有一个默认的隐式语句. super( ...
- java基础(八) 深入解析常量池与装拆箱机制
引言 本文将介绍常量池 与 装箱拆箱机制,之所以将两者合在一起介绍,是因为网上不少文章在谈到常量池时,将包装类的缓存机制,java常量池,不加区别地混在一起讨论,更有甚者完全将这两者视为一个整体, ...
- Java基础(八)--String(源码)、StringBuffer、StringBuilder
String源码:基于jdk1.8 public final class String implements Serializable, Comparable<String>, CharS ...
- java基础八 [序列化和文件的输入/输出](阅读Head First Java记录)
对象具有状态和行为两种属性.行为存在类中的方法中,想要保存状态有多种方法,这里介绍两种: 一是保存整个当前对象本身(通过序列化):一是将对象中各个状态值保存到文件中(这种方式可以给其他非JAVA程序用 ...
- 重学JAVA基础(八):锁的基本知识
1.线程状态 如上图,当我们新建一个线程,并start后,其实不一定会马上执行,因为只有操作系统调度了我们的线程,才能真正进行执行,而操作系统也随时可以运行其他线程,这时线程又回到可运行状态.这个过程 ...
- java基础(八)-----深入解析java四种访问权限
Java中的访问权限理解起来不难,但完全掌握却不容易,特别是4种访问权限并不是任何时候都可以使用.下面整理一下,在什么情况下,有哪些访问权限可以允许选择. 一.访问权限简介 访问权限控制: 指的是本类 ...
- 《温故而知新》JAVA基础八
集合接口与泛型 定义: 集合接口会操作一系列相同属性数据的对象类型的数据结构,类似于数组,但是相对于数组来说更显得高端大气 集合的接口分为Collention和Map两大类,不直接操作,而是通过子类的 ...
- Java基础(八)
IO流 概述与分类 Java中的IO流技术主要用于传输数据.典型的应用场景有:读写本地文件,上传下载文件等.按照数据传输的方向可以分为两种: l 输入流(Input):既让数据进入应用程序中. l ...
- java基础(八)之函数的复写/重写(override)
复写的意思就是子类对父类的修改. 复写的条件: 1.在具有父子类关系的两个类当中:2.父类和子类各有一个函数,这两个函数的定义保持一致(返回值类型.函数名.参数列表) 还是老样子,3个文件来说明. P ...
- java基础知识文章汇总
将之前的所有关于Java基础知识的随笔,整理成质量较高的十几篇随笔,几乎是好几篇比较零散的随笔合成现在的一篇,自认为还不错. java基础(一) 深入解析基本类型 java基础(二) 自增自减与贪心规 ...
随机推荐
- SQL Server 数据库启动过程,以及启动不起来的各种问题的分析及解决技巧
目前SQL Server数据库作为微软一款优秀的RDBMS,其本身启动的时候是很少出问题的,我们在平时用的时候,很少关注起启动过程,或者很少了解其底层运行过程,大部分的过程只关注其内部的表.存储过程. ...
- OpenLayers加载高德地图离线瓦片地图
本文使用OpenLayers最新版本V5.3.0演示:如何使用OpenLayer加载谷歌地球离线瓦片地图.OpenLayers 5.3.0下载地址为:https://github.com/openla ...
- 寻找最小矩形边框--OpenCv
好久没有写博客了 今天写一下比较常用的寻找矩形边框 ////////////////////////////寻找最矩形边框/////////////////////////////////////// ...
- day50——js补充
day50 前端内容回顾 HTML 标签分类 块级标签:div p h1-h6 form hr br ul li ol table标签 内联标签:span a img label input sele ...
- Python全栈开发相关课程
Python全栈开发 Python入门 Python安装 Pycharm安装.激活.使用 Python基础 Python语法 Python数据类型 Python进阶 面向对象 网络编程 并发编程 数据 ...
- golang 之 sql
golang提供了sql包查询数据 建立连接 导入第三方包 import( "database/sql" _"github.com/go-sql-driver/mysql ...
- 一些spring boot的配置
RabbitMQ与Redis队列对比 https://www.cnblogs.com/chinaboard/p/3819533.html Spring batch的学习 https://www.cnb ...
- windows操作系统更改 <远程桌面> 端口号
windows远程桌面连接默认使用的是3389端口,为了避免被他人扫描从而暴力破解远程服务器或者病毒入侵.可以将默认端口修改为其它端口,如8888,11111等.最好修改为10000以后的端口,这样可 ...
- Tomcat组件梳理—Digester的使用
Tomcat组件梳理-Digester的使用 再吐槽一下,本来以为可以不用再开一个篇章来梳理Digester了,但是发现在研究Service的创建时,还是对Digester的很多接口或者机制不熟悉,简 ...
- XXL-JOB使用命令行的方式启动python时,日志过多导致阻塞的解决方式
一.Runtime.getRuntime().exec()的阻塞问题 这个问题也不能算是XXL-JOB的问题,而是Java的Runtime.getRuntime().exec()造成的,Buffere ...