JAVA狂神随堂笔记
狂神说JAVA视频链接地址
我是跟着狂神说的课程做的笔记,首先很感谢狂神分享的课程,在此我也把我做的笔记分享出来,制作不容易,希望的到你们的小赞赞,不喜勿喷,谢谢大家啦!!!
笔记持续更新中…
打开CMD的方式
1. 开始菜单+Windows系统+命令提示符
2. Windows+R 输入cmd打开控制台(推荐使用)
3. 桌面鼠标右键+在终端中打开
4. 在文件夹地址栏输入cmd打开控制台(打开后的路径就此文件夹)
5. 在文件里鼠标右键+在终端中打开
常用的DOS命令
#盘符切换(切换到D盘) D:
#查看当前目录下的所有文件 dir
#切换目录 cd (跨盘符切换需要加 /d 例如(由D盘切换到c盘): cd /d c:)
#清理目录 cls
#退出终端 exit
#查看电脑ip ipconfig
#(利用DOS命令打开应用程序)calc 计算器 mspaint 画图工具 notepad 记事本
#ping命令
#创建test文件夹(即创建目录) md test
#创建a.txt文件 cd>a.txt
#删除a.txt文件 del a.txt
#删除test文件夹(即删除目录) rd test
JAVA语言特性
1、简单性(不支持多继承,也屏蔽了指针的概念)
2、纯面向对象
3、可移植性
卸载KDK
1. 删除java安装目录
2. 删除系统环境变量JAVA_HOME
3. 删除Path下关于JAVA的环境变量
4. 运行窗口执行 java -version发现不成功,说明卸载成功
安装JDK
1. 百度搜索JDK8,找到下载地址
2. 同意协议
3. 下载电脑对应的版本
4. 双击安装JDK
5. 记住安装到的路径
6. 查找高级系统设置找到环境变量
7. 配置JAVA_HOME环境变量
8. 测试JDK是否安装成功
9. 若java -version查看版本成功则说明安装成功
配置环境变量
可以在csdn等多个平台搜索 JAVA如何配置环境变量
第一个程序HelloWorld
1. 随便建一个文件夹,存放代码
2. 新建一个java文件
- 文件后缀名为java
- Hello.java
- 【注意】系统可能没有显示文件名后缀名,我们需要手动打开
3、编写代码
public class Test
{
public static void main(String[] args)
{
System.out.println("Hello,world!");
}
}
4. 编译javac java文件,会生成一个class文件
5. 运行class文件,java class文件
可能遇到的情况
- 每个单词的大小写不能出现问题,java是大小写敏感的
- 尽量使用英文
- 在一个java源文件中可以声明多个class,但是只能最多有一个类声明为class,而且要求声明为public的类名必须与源文件名相同
- 符号不能使用中文
java运行机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tujE3Xf1-1683978175335)(C:\Users\lenovo\AppData\Local\Temp\WeChat Files\ca521908161b0f203e2a92a14e6c259.jpg)]
IDEA快捷键
psvm 生成
public static void main(String[] args){
}
--------------------------------------------
sout 生成
System.out.println("Hello,world!");
注释
//这是单行注释
----------------------------
/*
这是
多行
注释
*/
----------------------------
/**
@Author 作者名字(此处的@Author是有作用的)
这是文档注释
*/
----------------------------
关键字和保留字
关键字:
被赋予了特殊的含义,用作专门用途的字符串
例如int float double ...
-----------------------------------
保留字:
现在java尚未使用,但以后可能作为关键字使用
例如const goto(目前我只知道有这两个)
标识符
标识符:
必须由大小写字母、$、_、数字组合而成
(不能使用关键字作为变量名或方法名,且不能以数字开头)
基本数据类型
基本数据类型
整数类型:
byte 占1个字节 范围:-128-127
short 占2个字节 范围:-32768-32767
int 占4个字节 范围:-2147483648-2147483647
long 占8个字节 范围:-9223372036854775808-9223372036854775807
(long类型在声明时必须以l或L结尾 long b = 31415926L )
--------------------------------------------------
浮点类型:
float 占4个字节
double 占8个字节
(float类型在声明时必须以f或F结尾 long b = 3.1415926L )
注意:最好完全避免使用浮点数进行比较,因为存在舍入误差,接近但不等于(此处并不是四舍五入)
--------------------------------------------------
字符类型:
char 占两个字节
--------------------------------------------------
boolean类型:占一位,只有true和false两个
转义字符
转义字符
\t 制表符
\n 换行
......
类型转换
运算中,不同数据类型先转化为同一类型,然后进行计算
----------------------------------------------
强制类型转换(高位到低位,可能导致内存溢出)
int a = 128;
byte b = (byte)a;
----------------------------------------------
自动类型转换(低位到高位,自动转换)
int a = 128;
double b = a;
----------------------------------------------
注意:
1、不能对布尔型进行转换
2、不能把对象类型转换为不相干的类型
3、在把高容量转化为低容量的时候,强制转换
4、转换的的时候可能存在内存溢出,或者精度问题!
5、当容量小的数据类型变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型
6、操作比较大的数的时候,注意溢出问题
7、JDK7新特性,数字之间可以用下划线分割
变量和常量
变量
类变量: static 关键字
实例变量:从属于对象:如果不初始化,会变成这个类型默认值(布尔值默认是false、除了基本类型,其余的默认都是null)
局部变量:必须声明和初始化值
注意事项:
1、每个变量都有类型,必须先定义,后使用
2、变量名必须是合法的标识符
3、变量声明是一个完整的语句,因此每一个声明必须以分号结束
----------------------------------------------------------------------------------------------------------
常量
常量可以理解为特殊的变量,它的值被设定后,在程序运行过程中不允许被改变
常量名一般使用大写字符
//修饰符,不存在先后顺序
final 常量名 = 值;
final double PI = 3.14;
变量的命名规则
包名:多单词组成时,所有字母都小写
类名、接口名:多单词组成时,所有单词的首字母大写
变量名、方法名:多单词组成时,除了第一个单词首字母小写,第二个单词开始所有单词的首字母大写
常量名:所有字母都大写,多单词使用下划线连接
运算符
算术运算符:+,-,*,/,%,++,--
赋值运算符:=
关系运算符:>,<,<=,>=,==,!=,instanceof
逻辑运算符:&&(与),||(或),!(非)
短路运算符:&(与),|(或),与逻辑运算符运算结果相同,区别在于逻辑运算符在已经判断出结果后,不会执行后面的判断,而短路运算符就算已经判断出结果,但还是会执行后面的判断
位运算符(效率高):&(只有1&1是1,否则是0),|(只有0|0的结果是0,否则是1),^(相同为0,不同为1),>>(向右移动一位),<<(向左移动一位),>>>(无符号右移,最高位无论是0还是1,空缺位都补0)
条件运算符:(条件)?语句1:语句2;
扩展赋值运算符:+=,-=,*=,/=
字符串连接符:+ (string可以与8中基本数据类型做连接运算,运算结果仍然为string型)
-----------------------------------------------------------------------------------------------------------
很多运算,我们会使用工具类来操作
比如幂运算要用到Math类
double pow = Math.pow(3,2)
计算的是2^3=8
包机制
为了更好的组织语言,JAVA程序提供 了包机制,用于区别类名的命名空间
(包的本质就是文件夹)
-----------------------------------------------------------------------------------
包语句的语法格式为:
package pkg1[[.pkg2].pkg3...];
-----------------------------------------------------------------------------------
!!一般利用公司域名倒置作为包名
为了能够使用某一个包的成员,我们需要在JAVA程序中明确导入该包。使用import语句可完成此功能
import package1[[.package2].classname]; (classname是类名,会导入package2这个包下所有的类)
import package1[[.package2].*]; (*是通配符,会导入package2这个包下所有的类)
-----------------------------------------------------------------------------------
注意:import必须在package下面!!!
JAVADoc生成文档
javadoc命令是用来生成自己的API文档
例如:使用命令行执行
javadoc -encoding UTF-8 -charset UTF-8 Main.java
设置编码为UTF-8和字符集编码为UTF-8(解决乱码问题)
/**
*@author kuangshen
*@version 版本号1.8
*/
----------------------------------------------
参数信息
@author 作者名
@version 版本号
@since 指明需要使用的jdk版本
@param 参数名
@return 返回值情况
@throws 异常抛出情况
使用IDEA下的javadoc执行命令
tools->generate JavaDoc->配置各项参数
用户交互Scanner
Scanner是一个类,在java.util这个包下面,用来获取用户的输入
基本语法:使用前先导包import java.util.Scanner;
Scanner s = new Scanner(System.in);//在堆上开辟空间
string str = s.next();//程序等待用户输入字符串
s.close();//由于在堆上开辟空间,及时释放以免浪费资源
-----------------------------------------------------------------------------------------------------------
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入数据
next():
1、一定要读取到有效字符后才可以结束输入
2、对输入有效字符之前遇到的空白,next()方法会自动将其去掉
3.只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
4, next() 不能得到带有空格的字符串
nextLine ():
1.以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符(当输入全部为空格时,结果为假)
2. 可以获得空白
顺序结构
JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句的执行
选择结构
if单选泽结构
if(条件){
执行语句;
执行语句;
}
-----------------------------------------------------------------
if双选择结构
if(条件){
执行语句;
执行语句;
}
else{
执行语句;
执行语句;
}
------------------------------------------------------------------
if多选择结构
if(条件){
执行语句;
执行语句;
}
else if(条件){
执行语句;
执行语句;
}
.....
else{
执行语句;
执行语句;
}
------------------------------------------------------------------
嵌套的if结构
if(条件){
if(条件){
执行语句;
执行语句;
}
}
------------------------------------------------------------------
switch多选择结构
switch语句中的变量类型可以是:
byte、short、int、char、(从JAVA SE 7开始支持字符串String类型了)
switch(变量){
case value1 :
执行语句;
执行语句;
break;
case value2 :
执行语句;
执行语句;
break;
case value3 :
执行语句;
执行语句;
break;
default :
执行语句;
执行语句;
}
循环结构
while循环(先判断后执行)
while(条件){
//循环内容;
}
----------------------------------------------------------------
do..while循环(先执行后判断,保证循环体至少执行一次)
do{
//循环内容;
}while(条件);
----------------------------------------------------------------
for循环
for(初始化;条件;更新){
//循环内容;
}
----------------------------------------------------------------
增强for循环:只能用来遍历集合和数组
for(遍历出来数据的类型:数组){
//循环内容;
}
break、continue、(goto保留字->标签)
1、break 跳出循环(break也在switch语句中使用)
2、continue 跳出本次循环,执行下次循环
3、标签不建议使用
output:for(初始化;条件;更新){
for(初始化;条件;更新){
if(条件){
continue output;
}
}
}
方法
JAVA的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
方法是语句的集合(本意是功能块),它们在一起执行一个功能
方法是解决一类问题的步骤的有序组合
方法包含于类或对象中
方法在程序中被创建,在其他地方被引用
!!!一个方法只完成一个功能,这样有利于我们后期的扩展
--------------------------------------------------------------------------
方法的命名规则:多单词组成时,除了第一个单词首字母小写,第二个单词开始所有单词的首字母大写
参数类型(形式参数、实参):参数是可选的,方法可以不包含任何参数
方法体:方法体包含具体的语句,定义该方法的功能
方法的重载
方法的重载: 重载就是在一个类中,有相同的函数名称,但形参不同的函数
方法的重载的规则:
1、方法名称必须相同
2、参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)
3、方法的返回类型可以相同也可以不相同
4、仅仅返回类型不同不足以成为方法的重载
实现理论:
方法名称相同时,编详器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错.
命令行传参
有时候你希望运行一个程序时候再传递给他消息,这要靠命令行传参
例如:
public class CommandLine{
public static void main(String args[]){
for(int i = θ; i < args.length; i++){
System.out.println("args[" +i+ "]: "+ args[i]);
}
}
}
普通参数和可变参数
JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法
在方法声明中,在指定参数类型后加一个省略号(...)
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它一之前声明(以便于分配内存空间)
--------------------------------------------------------------------------------------------------------
普通参数:
public class Demo01 {
public static void main(String[] args) {
Print(5);//是编辑器会自动填充的a :
}
public static void Print( int a ){
System.out.println(a);
}
}
--------------------------------------------------------------------------------------------------------
可变参数:
我对可变参数的理解,就是要传入同类型的数据,但不知道要传多少个,所以叫可变参数,等程序运行传入数据确定个数,参数此时类似于一个确定数目的数组!!!
public static void PrintMax(double... numbers){
if(numbers.length == 0){
System.out.println("No argument passed");
return;
}
double result = numbers[0];
//排序!
for(int i = 1;i< numbers.length; i++){
System.out.println(numbers[i]);
}
}
递归
递归
A方法调用B方法,我们很容易理解!
递归就是:A方法调用A方法!就是自己再用自己
利用递归可以用简单的程序来解决一些复杂的问题,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量,通归的能力在于用有限的语句来定文对象的无限集合
!!!但不推荐使用
递归结构包括两个部分:
递归头:什么时候不调用自身方法,如果没有头,将陷入死循环(可以理解为结束条件)
递归体:什么时候需要请用自身方法
------------------------------------------------------------------------------------------------------------
package com.baidu.www;
public class Demo01 {
public static void main(String[] arges) {
System.out.println(f(5));
}
public static int f( int n){
if (n == 1) {
return 1;
} else {
return n * f(n - 1);
}
}
}
数组的定义
数组的定义:
数组是相同类型数据的有序集合.
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成.
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们
数组的基本特点
数组的四个基本特点:
其长度是确定的,数组一旦被创建,它的大小就是不可以改变的
其元素必须星相同类型,不允许出现混合类型
数组中的元素可以是任何数据类型,包括基本类型和引用类型
数组变量属引用类型,数据也可以看成是对象,数据中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型。数组对象本身是在堆中的
数组的声明和创建
首先必须声明数组变量,才能在程序中使用数组,下面是声明数组变量的语法:
dataType[] arrayRefVar; // 首选的方法 int[] a;//数组的声明
或---------------------------------------------------------------------------------
dataType arrayRefVar[]; // 效果相同,但不是首选方法 int a[];//数组的声明
Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize]; int[] a = new int[10];
-----------------------------------------------------------------------------------
数组的元素是通过索引访问的,数组索引从 0 开始。
获取数组长度:
a.length
数组三种初始化及内存分析
三种初始化:
--------------------------------------------------------------------------------------------------------
静态初始化
int[] a={1,2,3};
动态初始化
int[] a = new int[3];
数组的默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此数组一般分配空间,其中的每个元素也被按照实判变量同样的方式被隐式初始化(C
中没有默认初始化)
--------------------------------------------------------------------------------------------------------
我当时存在的疑惑并找到如下结论:
!!!无论是静态初始化,还是动态初始化数组元素都是开辟在堆区上
1、静态初始化与C的区别:在于C的静态初始化可以直接指明长度 int a[3]={1,2,3}; ,C也可以不指定数组长度 int a[]={1,2,3};,由系统判断长度,但是java不能指明长度,只能由系统判断int a[]={1,2,3};
2、动态初始化区别:c语言格式为 int* a = new int[5]; ,JAVA格式为 int a[]= new int[5];
代码区:存放函数的二级制代码,由操作系统进行管理的
全局区:存放全局变量和静态变量(static)以及常量,程序结束才被释放
栈区:由编译器自动分配释放,存放函数的参数值,局部变量等
堆区: 由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
--------------------------------------------------------------------------------------------------------
数组下标越界
数组的长度是确定的,下标从0开始,如果越界,属于非法访问
会报错误:ArrayIndexOutofBounds
数组的使用
for循环等
数组作方法入参
数组作为返回值
---------------------------------------------------------------------------------
package com.baidu.www;
public class Demo01 {
public static void main(String[] arges) {
int[] a={1,6,0,3,8};
int[] b = printArray(a);
System.out.println(b);
}
public static int[] printArray(int[] arrays){ //返回类型为数组
for(int i = 0; i < arrays.length; i++){ //利用for循环使用数组
System.out.println(arrays[i]);
}
return arrays; //返回数组
}
}
二维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
二维数组:
动态初始化:
int a[][] = new int[2][5];
或静态初始化:
int a[][] = {{1,2},{2,3},(3,4),(4,5),{5,6}}
解析:以上二维数组 a可以看成一个两行五列的数组。
Arrays(数组工具)类
数组的工具类java.util.Arrays
由于数组对象本身井没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作,
查看JDK帮助文档
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用“使用对象来调用(注意:是“不用“而不是“不能“)
具有以下常用功能:
给数组赋值:通过fill 方法
对数组排序:通过 sort 方法,按升序
比较数组:通过 equals 方法比较数组中元素值是否相等
查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作
--------------------------------------------------------------------------------------------------------
package com.baidu.www;
import java.util.Arrays;//一点要导包
public class Demo01 {
public static void main(String[] args) {
int[] a={1,2,3,4,5,6,7,8,9};
Arrays.fill(a,1,5,6);//通过fill方法给下标1-4的数组元素赋值为6
System.out.println( Arrays.toString(a));//使用Arrays.toString()这个方法输出数组
}
}
冒泡排序法
优化前:
package com.baidu.www;
import java.util.Arrays;//一点要导包
public class Demo01 {
public static void main(String[] args) {
int[] a = {1, 4, 8, 3, 4, 6, 8, 7, 6, 0};
int[] sort = sort(a);//调用我们自己的排序方法
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array) {
int temp;
for (int i = 0; i < array.length - 1; i++) {
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j + 1] > array[j]) { //从大到小排序,若要从小到大改>为<
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
return array;
}
}
------------------------------------------------------------------------------------------
优化后:
package com.baidu.www;
import java.util.Arrays;//一点要导包
public class Demo01 {
public static void main(String[] args) {
int[] a = {1, 4, 8, 3, 4, 6, 8, 7, 6, 0};
int[] sort = sort(a);//调用我们自己的排序方法
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array) {
int temp;
for (int i = 0; i < array.length - 1; i++) {
boolean flag = false;
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j + 1] > array[j]) { //从大到小排序,若要从小到大改>为<
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag = true;
}
}
if(!flag)
{
break;
}
}
return array;
}
}
稀疏数组
对于增强for循环遍历二维数组的理解:
------------------------------------------------------------------------------------------------------------
先来说一维数组的遍历:
for(遍历出来数据的类型:数组){
//循环内容;
}
实例:
int[] b={1,2,3,4,5};
for(int x : b){
System.out.println(x);
}
输出结果为
1
2
3
4
5
可以这样理解:它是遍历b数组里面的每一个元素,第一次遍历的是b[0],并把b[0]的值赋值给x,第二次遍历的是b[1],再把值赋值给x(注意此时x发生了变化,x随着循环一直在更新),它循环的次数就是b数组中元素的个数,所以说输出结果为上面结果
------------------------------------------------------------------------------------------------------------
再来说遍历二维数组:
实例:
int[][] b={{1,2},{3,4},{5,6},{7,8}};
for(int[] x : b){
for(int y : x){
System.out.print(x+" ");
}
System.out.print("\n");
}
输出结果为:
1 2
3 4
5 6
7 8
可以这样理解:此时把{1,2},{3,4},{5,6},{7,8}看作四个元素,外层循环第一次遍历的是把{1,2}这个元素赋值给一维数组x,然后进入内存循环的第一次循环,内层循环把一维数组x再进行遍历,把值赋值给y(注意此时y发生了变化,y随着内层循环一直在更新),等内层循环结束后,再跳转到外层循环的第二次循环
代码块
代码块的基本介绍
代码块又称为初始化块,属于类中的成员【即 是类的一部分】,类似于类的方法,将逻辑语句封装在方法体中,通过{}包围起来
但和方法不同,没有方法名,没有返回值,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建类时隐式调用。
相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作。
场景:如果多个构造器中都有重复的语句,可以将重复部分抽取到代码块中,提高代码的重用性。
例如: 看电影时,我们要打开荧幕,再播放广告,等时间到了在播放正片,每播放新的一部影片时,我们都要重复打开荧幕和播放广告这个动作,我们就可以提出来放在代码块中,这样每次创建对象时,就会优先执行代码块中的内容。
-----------------------------------------------------------------------------------------------------------
public class CodeBook {
public static void main(String[] args) {
Movie movie = new Movie("银河补习班");
System.out.println("=============");
Movie movie1 = new Movie("人生大事");
}
}
class Movie{
private String name;
{
System.out.println("电影荧幕打开");
System.out.println("播放广告");
}
public Movie(String name) {
this.name = name;
System.out.println("电影"+name+"正在播放");
}
}
静态代码块
static代码块叫静态代码块,作用是对类进行初始化它随着类的加载进行初始化,而且随着类的加载而被执行并且只会执行一次。
如果是普通代码块,每次创建一个对象就执行一次。
类什么时候加载【重点】
- 创建对象实例时(new)
- 创建子类对象实例时,父类也会被加载
- 使用类的静态成员时(静态属性,静态方法)
代码块的使用小细节
-
普通的代码块,在创建对象实例时,会被隐式的调用。每被创建一次,就会调用一次。
-
静态代码块只在类加载时创建且只创建一次,而普通代码块每创建一次对象就调用一次。
-
如果只是使用类的静态成员时,普通代码块并不会执行。
存在继承关系时,类中的调用顺序
- 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
- 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
- 父类的普通代码块和普通属性的初始化(优先级一样,按定义顺序执行)
- 父类的构造方法
- 子类的普通代码块和普通属性的初始化(优先级一样,按定义顺序执行)
- 子类的构造方法
public class TestD {
public static void main(String[] args) {
D d=new D();
}
}
class D extends E{
public D() {
System.out.println("子类D的无参构造器被调用");
}
{
System.out.println("子类D的普通代码块被调用");
}
private int n2 = getn2();
private static int n1=getn1();
static{
System.out.println("子类D的静态代码块被调用");
}
public static int getn1(){
System.out.println("子类getn1被调用");
return 100;
}
public int getn2(){
System.out.println("子类getn2被调用");
return 99;
}
}
class E{
public E() {
System.out.println("父类E的无参构造器被调用");
}
{
System.out.println("父类E的普通代码块被调用");
}
private int n2 = getn4();
private static int n1=getn3();
static{
System.out.println("父类E的静态代码块被调用");
}
public static int getn3(){
System.out.println("父类的getn3被调用");
return 100;
}
public int getn4(){
System.out.println("父类的getn4被调用");
return 99;
}
}
静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员
常用类
成员内部类
内部类依赖于外部类,要创建内部类首先要创建外部类
例如:
public class Main {
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
inner.show();
/*
或者
Outer outer =new Outer();
Outer.Inner inner = outer.new Inner();
inner.show();
*/
}
}
//输出结果为:
李四
张三
------------------------------------------------------------------------------------------------------------
在另一个包里创建:
public class Outer {
private String name="李四";
public class Inner{
public void show() {
private String name="张三";
System.out.println(Outer.this.name);
System.out.println(name);
}
}
}
**内部类和外部类属性相同时,在内部类访问优先访问内部类的属性,要想访问外部类则需要将 属性名 改为 外部类名.this.属性名 **
成员内部类不能定义静态成员( static int c = 0; ),可以定义静态常量( static final int c = 0; )
外部类权限修饰符只有public和default,而内部类与属性、方法同级别,修饰符有public、protected、default、private
静态内部类
不依赖于外部类对象,可以直接创建或通过类名访问,可声明静态成员
静态内部类与外部类相同
public class Main {
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
inner.show();
}
}
-----------------------------------------------------------------------------------------------------------
package com.baidu.bbb;
//外部类
public class Outer {
private String name ="xxx";
private int age =18;
public static class Inner{
private String address ="上海";
private String phone ="111";
//静态成员
private static int count =1000;
public void show(){
//调用外部类的属性
//1、先创建外部类对象(这样才会有外部类属性,因为外部类属性从属于对象)
Outer outer =new Outer();
//2、调用外部类对象的属性
System.out.println(outer.name);
System.out.println(outer.age);
//调用静态内部类的属性和方法
System.out.println(address);
System.out.println(phone);
//调用静态内部类的静态属性(此处加不加 Inner. 都行)
System.out.println(Inner.count);
}
}
}
局部内部类
局部内部类定义在外部类方法中,作用范围和创建对象范围仅限于当前方法,不能加任何修饰符
局部内部类中的方法访问局部变量时,变量必须为常量!!!(jdk1.8会自动添加final)
局部内部类不能包含静态成员,但是可以有静态常量
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.show();
}
}
----------------------------------------------------------------------------------------------------------
package com.baidu.bbb;
//外部类
public class Outer {
private String name ="刘德华";
private int age =35;
public void show(){
//定义局部变量
String address="深圳";
//局部内部类,注意不能加任何访问修饰符
class Inner{
//局部内部类的属性
private String email ="liudehua@qq.com";
private String phone ="111";
//静态成员
public void show2(){
//访问外部类的属性
System.out.println(Outer.this.name);
System.out.println(Outer.this.age);
//访问内部类的属性,this可要可不要
System.out.println(this.phone);
System.out.println(this.email);
//访问局部变量,jdk1.7要求,变量必须为final,jdk1.8自动添加final
//在局部内部类中如果不访问局部变量,就是普通的变量,在此时不是final常量,可以修改
System.out.println(address);
}
}
//创建内部类对象
Inner inner=new Inner();
inner.show2();
}
}
匿名内部类
没有类名的局部内部类(一切特征与局部内部类相同)
必须继承一个父类(普通的父类或者抽象的父类)或者实现一个接口
定义类、实现类、创建对象的语法合并,只能创建一个该类的对象
优点:减少代码量
缺点:可读性较差
package com.baidu.bbb;
//接口
public interface Usb {
//服务
void service();
}
-----------------------------------------------------------------------------------------------------------
public class Mouse implements Usb {
@Override
public void service() {
System.out.println("连接成功,鼠标开始工作了...");
}
}
----------------------------------------------------------------------------------------------------------
package com.baidu.bbb;
public class TestUsb {
public static void main(String[] args) {
//创建接口类的变量
/*Usb usb =new Mouse();
usb.service();*/
//局部内部类实现接口
// class Fan implements Usb {
// @Override
// public void service() {
// System.out.println("连接电脑成功,风扇开始工作啦...");
// }
// }
//使用局部内部类创建对象
// Usb usb=new Fan();
// usb.service();
//使用匿名内部类优化(相当于创建了一个局部内部类)
Usb usb =new Usb(){
@Override
public void service() {
System.out.println("连接电脑成功,风扇开始工作啦...");
}
};
usb.service();
}
}