该片为基础入门阶段,内容会随着日常积累不断完善和深化
一、总览 1.开发过程
注:详细底层的编译执行过程会在JVM篇中详细整理
- JDK
JVM:Java虚拟机
JRE:Java运行环境,除了包含JVM以外还包含了运行java程序所必须的环境
JRE=JVM+java系统类库(小零件)
JDK:Java开发工具包,除了包含JRE以外,还包含了开发Java程序所必须的命令工具
JDK=JRE+编译、运行等命令工具
开发工具运行Java程序的最小环境为JRE
开发Java程序的最小环境为JDK
Eclipse、idea …
注释1)单行注释:// 2)多行注释: 3)文档注释:二、变量 1、变量
1.1、变量的初始化变量是代词,内存中开辟的一块存储区域,用于存储临时变量。
1.2、变量的使用1)声明的时候初始化:int a=25;//声明变量a并赋值为25
2)先声明后初始化:int a;//声明变量a a=3;//给变量a赋值为3
1.3、实例变量和静态变量对变量的使用就是对它存的那个数的使用。
1)变量在使用是必须类型匹配
2)变量在用之前必须声明并初始化。
1.4、变量命名规则实例变量依赖于对象,静态变量依赖于类,跟对象无关。
实例变量用对象去调用,静态变量用类名调用
二、基本数据类型4.1)只能包含字母、数字、下划线和$符,不能以数字开头
4.2)严格区分大小写
4.3)不能使用关键字
4.4)可以中文命名,但不建议。
建议"英文见名知意"、“驼峰命名法”
1.1)自动类型转换:小类型到大类型
1.2)强制类型转换:大类型到小类型
eg: (要转换成为的数据类型)变量
强转有可能溢出或丢失精度
- 整数直接量,直接写出的整数,默认是int型,可以给byte、short、char赋值,但不能超范围。
- byte,short,char类型参与运算时,先一律转换为int再运算*。
- 表示长整型直接量,需要在数字后加L
- 浮点数直接量默认为double型,若想表示float需在数字后加F
- double和float在运算时,有可能会出现设入误差(精确运算场合不能使用)
- char:字符型,2个字节采用Unicode字符集编码,一个字符对应一个码(0-65535之间)、表现的形式是字符char,但本质上时码int
- ASCII码(‘a’–97 ‘A’–65 ‘0’–48)
+ - * / % ++ --
- a++:先赋值,后++
- ++a:先++,后赋值
- 单独使用的话值都+1
2%8//2,商0余2
2, 关系运算符(6个)boolean值
< >= <= == !=
关系运算符的结果为boolean型,关系成立则为true,关系不成立则为false
3,逻辑运算符(3个)boolean值
&& || !
3.1)&&:短路与(并且),两边都为真则为真,见false则false
当第一个数为false时,则发生短路(后面的不执行了)
||:短路或(或者),有一边为真则为真,见true则true
当第一个数为true时,则发生短路(后面的不执行了)
!:逻辑非(取反),
3.2)逻辑运算是建立在关系运算符的基础之上的,逻辑运算的结果也是boolean型。
//ac
4,赋值运算符(6个)
= += -= /= *= %=
细分:4.1)简单赋值 :=
4.2)扩展赋值:+= -= /= *= %=
注意:扩展赋值自带强转功能
面试题:
short s=5;
s+=10;//相当于 s=(short)(s+10);
//s=s+10;编译错误,需要强转
5,字符串连接符 +
5.1)若两边为数字,则做加法 *** 作
5.2)若两边出现了字符串,则做字符串连接
6,三目(条件)运算符
boolean表达式?数1:数2
执行过程:
计算boolean的值:
若为true,则整个表达式的结果为数1
若为false,则整个表达式的结果为数2
什么是表达式
是由运算符和运算对象组成的。
—day 04--------------
顺序-分支-循环
二,分支结构
1)if结构:1条路
2)if…else结构:2条路
3)if…else if 结构:多条路
4)switch…case 结构:多条路
优点:效率高、结构清晰
缺点:
switch只能对固定的几个值进行判断,不能判断范围。判断的值的类型有限(整数/enum/string)。
break:跳出switch
if可以用于判断数值,也可以判断区间,
只要运算结果是boolean类型,都可以进行判断。
2,循环:反复执行一段相同或相似的代码
3,循环三要素:
1)循环变量的初始化
2)循环的条件(以循环变量为基础)
3)循环变量的改变(向着循环的结束变)
循环变量:在整个循环过程中所反复改变的那个数
int a=0;//循环变量的初始化
while(a<3){//循的条件
…
a++;//循环变量的改变
}
while循环的执行过程:
a=0
true 输出 a=1
true 输出 a=2
true 输出 a=3
false while循环结束
4,循环结构
1)while 结构:先判断后执行,有可能 一次都不执行
2)do…while 结构:先执行后判断,至少执行一次
套路: 要素1:与要素3相同时,首选 do…while
----day 05----------------
3)for结构:应用率最高,固定次数循环
2.break:跳出当前循环
continue:跳过循环体中剩余语句而进入下一次循环
3.三种循环结构的更佳使用情况:
1)while :“当…”
2)do…while:"直到…”
要素1与要素3相同时首选do…while
3)for:固定次数循环,应用率高
4.嵌套循环:
1)循环中套循环,一般多行多列同时使用,外层控制行,内层控制列
2)执行规则:外层循环走一次,内层循环走所有次
3)建议:嵌套层数越少越好,能用一层就不用两层,能用两层就不用三层
若需求必须要使用三层以上的循环才能解决,说明设计有问题。
4)break 只能跳出一层循环。
5.程序=算法+数据结构------------了解
1)算法:解决问题的流程/步骤(顺序、分支、循环)
2)数据结构:将数据按照某种特定的结构来保存
数怎么存
设计良好的/合理的数据结构会导致好的算法
6.数组:
数组就是简单的线性序列,这使得元素访问非常快速。
代价就是数组对象的大小固定,并且在其生命周期中不可改变。
数组用[]来访问元素。
对象数组保存的是引用,基本类型数组保存基本类型的值。
***java编程思想之引用:
应用类型变量简称引用;
new的意思可以理解为给我一个新对象。对引用的 *** 作就是对new的对象的的 *** 作。
1)是一种数据类型(引用类型)
2)相同数据类型元素的集合
3)数组的定义:
int[] arr = new int[10];//用new表达式显式的创建
4)数组的初始化:
int[] arr = new int[3]; //0,0,0
int[] arr = {2,5,8}; //2,5,8
int[] arr = new int[]{2,5,8}; //2,5,8
int[] arr;
arr = {2,5,8}; //编译错误,此方式只能声明同时初始化
arr = new int[]{2,5,8}; //正确
****扩展:
变量只能存储一个类型的对象,为了存放多个相同类型的对象,而数组长度固定,使用不方便,所以有了集合,用来存放统一类型的对象,而且长度不固定,随元素自增,不用扩容。为了限制集合类型,就有了范型,规定集合内的元素类型。
----day 06 --------------------
1.数组:
5)数组的复制
5.1)Java标准类库中有static方法 System.arraycopy(src, srcPos, dest, destPos, length)
效率高,灵活性好
5.2)int[] a1=Arrays.copyOf(a,6)//效率低,灵活性差
a=Arrays.copyOf(a,a.length+1)//数组的扩容/缩容
src - 源数组。
srcPos - 源数组中的起始位置。
dest - 目标数组。
destPos - 目标数据中的起始位置。
length - 要复制的数组元素的数量。
6)数组的排序:
6.1)Arrays.sort(arr);//升序,效率高
6.2)冒泡排序:–先确定尾
6.2.1)n个数冒n-1轮
6.2.2)每一轮都是从第一个元素开始冒泡,每一次都是和它的下一个元素比
6.3.3)冒出来的就不再参与比较了。
2,方法:
封装了一段特定的业务逻辑功能,尽可能独立,只干一件事,反复调用,减少重复,有利于维护,有利于团队协作。
3,方法的定义:
修饰词 返回值类型 方法名(参数列表){//形参
方法体
}
方法名和参数列表唯一的标识出某个方法
Java中的方法只能作为类的一部分来创建。方法只有通过对象才能被调用,且这个对象必须能执行这个方法调用。
static方法,它是针对类调用的,并不依赖对象的存在。
4,方法的调用:
1)无返回值:直接写 方法名(有参传参);//实参
2)有返回值:数据类型 变量=方法名(有参传参);
5,retuen:
1)return 值;//1.1结束方法的执行。1.2返回结果给调用方
2)return;/// 结束方法的执行)(在某种条件下提前结束方法)
----day 07----------
一,猜字符小游戏
1.设计数据结构:变量
1)char[] chs;//随机字符数组
2)char[] input;//用户输入的字符数组
3)int[] result;//对比的结果
4)int score;//得分
- 设计程序结构:方法
1)主方法:public static void main(String[] args){…}
2)生成随机字符数组:
public static char[] generate(){
char[] chs=new char[5];
return chs;
}
3.设计算法:方法体
三种引用类型:数组、类、接口
栈内存:
存储的都是局部变量。只要是在方法中定义的变量都是局部变量。
一旦变量的生命周期结束该变量就被释放
堆内存
存储的都是实体(对象)
每一个实体都有一个首地址值。
堆内存的变量都有默认初始化。
当实体不再使用时,就会被垃圾回收机制处理。
-----面向对象08 对象 - ----------------
笔记:
OOP:面向对象的编程
1.什么是类?什么是对象?
1)现实世界是由很多很多对象组成的
基于对象抽出了类
2)对象:真实存在的单个的个体
类:类型/类别,代表一类个体(一类事物的总称)
5)“类是对象的模板,对象是类的具体的实例”
Java中类是指的一种数据类型
3)类中可以包含:
3.1)所有对象所共有的属性/特征----成员变量
3.2)所有对象所共有的行为-----方法
4)一个类可以创建多个对象,
同一类型所创建的对象,结构相同,数据不同
2.如何创建类?如何创建对象?如何访问成员?
****java编程思想{*1.万物皆对象。将对象视为奇特的变量,它可以存储数据,除此之外,你还可以要求它在自身上执行 *** 作。理论上讲,你可以抽取待求解决问题的任何概念化结构(狗,建筑物,服务等)将其表示为程序中的对象。*2.程序是对象的集合,他们通过发送消息来告知彼此要做的事。–>要向请求一个对象就必须对该对象发送一条消息。更具体的说,可以把消息想象为对某个特定对象的方法的调用。*3.每个对象都有自己的有其他对象所构成的储存。—>换句话说,可以通过创建包含现有对象的包的方式来创建新类新的对象。因此,可以在程序中构建复杂的体系,同时将其复杂性隐藏在简单性的背后。*4.每个对象都拥有其类型。–>每个对象都是某个类的实例,每个类最重要的区别在于其他类的特性就是‘可以发送什么样的消息给它。’*5.某一特定类型的所有对象都可以接收同样的消息。–>对象都具有状态,行为和标示。}
-----面向对象09- ----------------
成员变量和局部变量是可以同名的,
但是用的时候-------采用就近原则
当成员变量与局部变量同名时,this不能省略
内存管理:由JVM来管理的
1)堆:所有new出来的对象(包括成员变量)
2)栈:方法中的局部变量(包括方法的参数)
3)方法区:.class字节码文件(包括方法)
0,方法的签名:方法名+参数列表
1,方法的重载(Overload):
1)发生在同一个类中,“方法名称相同,参数列表不同”,方法体不同
2)编译器在编译时会根据方法的签名自动绑定调用的方法
2,“构造方法”:
1)给成员变量赋初值(“成员变量显示初始化”)
2)与类同名,没有返回值类型
3)在创建对象时被自动调用
4)若自己不写构造方法,则编译器默认创建一个无参构造方法
若自己写了构造方法,则不再默认提供
5)构造方法可以重载
3,this:指代当前对象,哪个对象调用方法 它指的就是哪个对象
只能用在方法中,方法中访问成员变量之前默认有个this。
this的用法:
1)this.成员变量——访问成员变量
2)this.方法名()——调用方法(一般不用)
3)this()——调用构造方法
4,null:空,没有指向任何对象
若引用的值为null,则该引用不能再进行任何 *** 作了
若 *** 作则发生NullPointerException空指针异常
注:“引用”,引用类型变量的简称
5,引用类型之间画等号:
1)指向同一个对象
2)通过一个引用对数据的修改会影响另一个引用对数据的访问
eg.房子钥匙
基本类型之间画等号
1)赋值
2)对一个变量的修改不会影响另一个变量
eg:身份z复印件
“Demo d=new Demo();”
1,加载Demo.class文件进方法区,并进行空间分配。
2,如果有静态变量,先默认初始化,再显示初始化。
3,如果有静态代码块,要执行,仅一次
4,通过new在堆内存中开辟 ,并明确首地址。
5,对对象中的属性进行默认初始化。
6,调用对应的构造函数进行初始化
7,构造函数内部:
7.1调用父类构造函数super();
7.2成员变量的显示初始化。
7.3构造代码块初始化。
7.4构造函数内自定义内容初始化。
8,对象初始化完毕后,将地址值赋值给d引用变量。
注释:“方法区”
-----面向对象10 - ----------------
1.引用类型数组:
//创建Student数组对象
1)Student[] stus = new Student[3];
stus[0] = new Student(“zhangsan”,25,“LF”);//创建Student对象
stus[1] = new Student(“lisi”,26,“JMS”);
stus[2] = new Student(“wangwu”,24,“SD”);
2)Student[] stus = new Student[]{
new Student(“zhangsan”,25,“LF”),
new Student(“lisi”,26,“JMS”),
new Student(“wangwu”,24,“SD”)
};
/声明int[]的数组arr,包含3个元素,每个元素都是int[]型,默认值为null/
3)int[][] arr = new int[3][];------------数组的数组
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[2];
arr[1][0] = 100;
4)int[][] arr = new int[3][4]; //3行4列
for(int i=0;i
for(int j=0;j
arr[i][j] = 100;
}
}
2.继承:
1)作用:减少代码的重复,有利于代码复用。。。。。
2)通过extends来实现继承
3)父类:所有子类所共有的属性和行为
子类:子类所特有的属性和行为
4)子类继承父类后,子类具有:子类的+父类的
5)一个父类可以有多个子类
一个子类只能有一个父类----------“单一继承”
6)继承具有"传递性"的
7)java规定:在构造子类之前必须先构造父类
在子类的构造方法中若没有调用父类的构造方法
------则默认super()调用父类的无参构造方法
在子类的构造方法中若自己调用了父类的构造方法
------则不再默认提供
super()调用父类构造方法必须位于子类构造方法的第一行
“this代表:当前对象的引用”
“super代表:父类的内存空间!!!”
this:指代当前对象====当前对象的引用
3.super:指代当前对象的父类对象(不准确)=====父类的内存空间
super的用法:
1)super.成员变量名-------------访问父类的成员变量
2)super.方法名()---------------调用父类的方法---------明天讲
3)super()----------------------调用父类的构造方法
子类中的构造器为什么有一句隐式的super()??
原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作。才可以更为方便的使用父类的内容。
***调用父类构造器是真的,但是根本没有创建父类对象,只不过是调用父类构造器来初始化属性。
super关键字只不过是访问了new出来的空间里的特定的数据(也就是专门存储父类数据的内存部分)
默认的hascode和equals都是一样的,所以,根本就在一个空间里,也不存在单独的出来的父类对象。(super.equels(this))//true
说明:
1.继承要符合is a(是一个)的关系
2.问:子类可以继承父类的构造方法吗?
答:不可以,父类构造方法是由子类来调用的
-----面向对象11 - ----------------
1,向上造型:
1)父类的引用指向子类的对象
2)能点出来什么(.) ,看引用的类型
【如果必须使用向上造型,则继承是必须的】
提高扩展性,隐藏子类型,不需要使用子类的特有方法。
向下造型:需要使用子类型特有的内容,注意:一定要instanceof判断类型,避免ClassCastException
总结:对于成员变量和静态方法,编译和运行都看左边。“对于成员方法,编译看左边,运行看右边。原因是方法有重写,而是是动态绑定到对象上。”
2,方法的重写(覆盖)(Override):
1)发生在父子类中,“方法名相同,参数列表相同”,方法体不同
2)重写方法被调用时,看对象的类型
什么时候用重写??****
子类使用父类的功能,但是需要定义自己的功能内容。需要重写。
3)重写遵循"两同两小一大"原则:—了解
3.1)两同:
3.1.1)方法名称相同
3.1.2)参数列表相同
3.2)两小:
3.2.1)子类方法的返回值类型小于或等于父类方法的返回值类型(引用类型)
1)void时,必须相等
2)基本数据类型时,必须相等
3)引用数据类型时,“小于或等于”(父类大,子类小)
3.2.2)子类方法抛出的异常小于或等于父类方法的-------异常之后讲
3.3)一大:
3.3.1)子类方法的"访问权限"大于或等于父类方法的-------明天讲
3.重写与重载的区别:---------------常见面试题
1)重写(Override):
1.1)发生在父子类中(继承关系),方法名称相同,参数列表相同,方法体不同
1.2)遵循"运行期"绑定,看对象的类型来调用方法
2)重载(Overload):
2.1)发生在一个类中,方法名称相同,参数列表不同,方法体不同
2.2)遵循"编译期"绑定,看参数/引用的类型来绑定方法
重载看参数/引用,重写看对象
【总结】
当一个类是另一个类中的一种时,可以通过继承,来扩展功能。
如果从父类具备的功能内容需要子类特殊定义时,使用重写。
【实例化过程的细节】
1,如果子类的构造函数第一行写了this调用了本类其他构造函数,那么super调用父类的语句还有吗?
没有的,因为this()或者super(),只能定义在构造函数的第一行,因为初始化动作要先执行。
1.package:
1)避免类名的冲突
2)包名可以有层次结构,同包中的类不能同名
3)类的全称为:包名.类名
4)建议:包名所有字母小写
import:
1)同包中的类可以直接访问
不同包中的类不可以直接访问,想访问只有如下两种方式:
1.1)先import声明类再访问类——建议
1.2)类的全称——太繁琐 2.访问控制修饰符:
1)public:公开的,任何类
2)private:私有的,本类
3)protected:受保护的,本类,子类,同包类
4)默认的:什么也不写,本类,同包类(包访问权限)
说明:
1)类的访问修饰符只能是public或默认的
2)类中成员的访问修饰符如上都可以
注意:内部类可以用private和static等修饰(放在成员位置上)
3.fianl:最终的、不可改变的——应用率低
1)修饰变量:变量不能被改变
2)修饰方法:方法不能被重写
3)修饰类:类不能被继承
final修饰成员变量,必须如下方式两种初始化:
1)声明的同时初始化
2)在构造方法中初始化
final修饰局部变量,只要在用之前初始化即可
可以给private方法添加final修饰词,但这并不能给该方法增加任何额外的意义。
由于final类禁止继承,所以final类中所有的方法都隐式指定为是final的,因为无法重写他们。在final类中可以添加final修饰词,但不会增加任何意义。
4.static:静态的['stætɪk]
1)静态变量:
1.1)由static修饰的
1.2)属于类的,存储在方法区中,只有一份
1.3)常常通过 类名. 来访问。
1.4)何时用?所有对象所共享的数据(图片、音频、视频等)
声明为static的变量实质上是全局变量
2)静态方法:
2.1)由static修饰的
2.2)属于类的,存储在方法区中,只有一份(被所有对象共享)
2.3)常常通过类名.来访问。
2.4)静态方法没有隐式this传递的,静态方法中不能直接访问实例成员
2.5)何时用?方法的 *** 作仅与参数相关而与对象无关
静态方法可以被继承,但不能被重写(只有普通的方法可以是多态的)
3)静态代码块:static{…}
3.1)由static修饰的
3.2)在类被加载期间自动执行,因类只被加载一次,所以静态块也只执行一次
3.3)何时用?初始化/加载静态资源(图片、音频、视频等)
注意:构造器也是static方法。类是在其任何static成员被访问时加载的。
构造代码块: { }
只要创建对象就会被调用。给所有对象初始化。
???代码复用的概念!!!
一段代码在多个地方调用
-----面向对象13 - ----------------
正课:
1.static final常量:
1)必须声明同时初始化
2)常常通过类名点来访问、不能被改变
3)建议:常量名所有字母都大写,多个单词之间用_分隔
4)编译器在编译时会将常量直接替换为具体的值,效率高
5)何时用:数据永远不变,并且经常使用
2.抽象方法:
1)由abstract修饰
2)只有方法的定义,没有具体的实现(连{}都没有)
3.抽象类:
1)由abstract修饰
2)包含抽象方法的类必须是抽象类
不包含抽象方法的类也可以声明为抽象类-------我乐意
3)抽象类不能被实例化
4)抽象类是需要被继承的,子类:
4.1)重写所有抽象方法------变不完整为完整
4.2)也声明为抽象类--------不常用
5)抽象类的意义:
5.1)封装子类所共有的属性和行为--------代码复用
5.2)为所有子类提供一种统一的类型------向上造型
5.3)可以包含抽象方法,为所有子类提供统一的入口。
子类的具体实现不同,但入口是一致的
-----面向对象14- ----------------
1.成员内部类:应用率低
1)类中套类
2)内部类对象通常时在外部类中创建的
3)内部类中可以直接访问外部类的成员(包括私有的)
内部类中有个隐式的引用指向了创建它的外部类对象???
例如:外部类名.this.
2.匿名内部类:
1)若想创建一个类(子类)的对象,并且对象只被创建一个,此时该类不必命名,称之为匿名内部类
2)jdk1.7(含)之前,匿名内部类中想访问外面的变量,该变量必须时final 的
“面试题”
问:内部类有独立的.class吗?“有有有”
-----面向对象15 - ----------------
1.接口:
1)是一种数据类型(引用类型)
2)由interface定义
3)只能包含常量和抽象方法
4)接口不能被实例化
5)接口是需要被实现/继承得,实现类/派生类。 接口可以指向它的实现类。必须重写接口中得所有抽象方法
例:Collection c=new ArrayList(); Collection 是接口,指向了他的实现类AyyarList。
List list=new ArrayList();//List 集合是Collection的子类(派生类),它指向了实现类,ArrayList.
必须重写接口中得所有抽象方法
6)一个类可以实现多个接口,用逗号分隔
若又继承又实现,必须先继承后实现
7)接口 继承接口
1,抽象类是描述事物的基本功能,可以定义非抽象的方法。
接口中定义只能是抽象方法,负责功能的扩展。
jdk8可以定义静态方法
2,类与类之间是继承关系 is a关系。
类与接口之间是实现关系 like a 关系。
接口的思想:
举例:笔记本电脑,USB接口的故事。
1,接口的出现对功能是实现了扩展。
2,接口的出现定义了规则。
3,接口的出现降低了耦合性(解耦)。
接口的出现,完成了解耦,说明有两方,一方在使用这个规则,另一方在实现这个规则。
比如笔记本电脑使用这个规则,而外围设备在实现这个规则。
“设计规则”:
1.将所有子类所共有得属性和行为,抽到父类中——抽共性
2.子类的行为都一样,设计为普通方法
子类的行为不一样,设计为抽象方法
3.将部分子类所共有的行为,设计到接口中
符合即是也是原则时,使用接口
接口是对继承单根性的扩展——实现多继承
当程序的运行结果与你的预期结果不符时:
1)打桩: System.out.println(数据);
2)Debug调试:--------先添加断点
2.1)掌握四个键:
2.1.1)F5:单步调试(会进入到方法中)
2.1.2)F6:逐过程调试(不会进入到方法中)
2.1.3)F7:结束方法的调试
2.1.4)F8:直接跳到下一个断点(若后面没有断点则结束调试)
2.2)会看两个东西:
2.2.1)会看变量
2.2.2)会添加监视(选中表达式右键Watch)
***java编程思想:
-----面向对象16 - ----------------
多态:
【体现】父类的引用或者接口的引用指向了自己的子类(或实现类)的对象
【好处】提高了程序的扩展性
【弊端】通过父类的引用 *** 作子类对象时,只能使用父类中已有的方法啊,不能 *** 作子类特有的方法
【多态存在的必要条件】1,要有继承或实现2,要有重写 *** 作3,父类的引用指向子类对象
【多态的实现方式】
接口实现2,继承父类进行方法重写,3,同一个类中进行方法重载
实现技术
动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
1.多态:
1)多态的意义:
1.1)同一类型的引用指向不同的对象时,有不同的实现
——“行为的多态”:cut(),step(),getImage()…
1.2)同一个对象被造型为不同的类型时,有不同的功能
——“对象的多态”:我,你,水,被撞的敌人
2)向上造型/自动类型转换
2.1)超类型的引用指向派生类的对象
2.2)能造型成为的类型有:超类+所实现的接口
2.3)能点出来什么,看引用的类型
3)强制类型转换,成功的条件只有如下两种:
3.1)引用所指向的对象,就是该类型。
3.2)引用所指向的对象,实现该接口或继承该类
4)强转时若不符合如上两个条件,则发生ClassCastException类型转换异常,
建议:强转之前先通过"instanceof"来判断引用的对象是否时该类型。
注意:无论向上还是向下转型,最终都是子类对象做着类型的变化。
-----面向对象17- ----------------
面向对象的三大特征:
1.封装:
隐藏行为细节,保证数据安全
1)类:封装的是对象的属性和行为
2)方法:封装的是一段特定的业务逻辑功能
3)访问控制修饰符:封装的是具体访问的权限
2.继承:
1)作用:代码复用
2)超类:所有派生类所共有的属性和行为
接口:部分派生类所共有的行为
派生类:派生类所特有的属性和行为
3)传递性:单一继承、多接口实现
3.多态:
1)意义:行为的多态(所有抽象方法都是多态的)
对象的多态(所有对象都是多态的)
2)向上造型、强制类型转换、instanceof判断
3)多态的表现形式:
3.1)重写:根据对象的不同来实现多态
3.2)重载:根据参数的不同来实现多态
1.内存空间:由JVM来管理
1)堆:
java堆是被所有线程共享的一块区域
1.1)存储new出来的对象(包括实例变量)
1.2)垃圾:没有任何引用所指向的对象
垃圾回收器(GC)不定时到内存中清扫垃圾,回收过程是透明的(看不到的),不一定一发现垃圾就立刻回收,调用System.gc()建议虚拟机尽快调度GC来回收垃圾
1.3)实例变量的生命周期:
创建对象时存储在堆中,对象被回收时一并被回收
1.4)内存泄露:不再使用的对象还没有被及时的回收
建议:不再使用的对象及时将引用设置为null
2)栈(先进后出):
java虚拟机栈是线程私有的
2.1)存储正在调用的方法中的所有局部变量(包括方法的参数)
2.2)调用方法时在栈中为该方法分配一块对应的"栈帧",栈帧中包含局部变量(包括方法的参数),方法调用结束时,栈帧被清除(d栈)
2.3)局部变量的生命周期:
调用方法时存储在栈中(压栈),方法结束时栈帧被清除,局部变量一并失效
3)方法区:
方法区也是所有线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、方法等数据。
3.1)存储.class字节码文件(包括方法、静态变量)
3.2)方法只有一份,通过this来区分具体的调用对象
方法区:
在JVM中,方法区是可供各条线程共享的运行时内存区域。它存储了每一个类的结构信息,例如,“运行时常量池”、字段和方法数据、构造函数和普通方法的字节码内容、还包括一些在类、实例、接口初始化时用到的特殊方法
方法区在虚拟机启动的时候被创建,虽然方法区是堆的逻辑组成部分,但是简单的虚拟机实现可以选择在这个区域不实现垃圾收集。
====================
运行时常量池:
jvm在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。
它是每一个类或接口的常量池的运行时表示形式,它包括了若干种不同的常量:从编译期可知的数值字面量到必须运行期解析后才能获得的方法或字段引用。
每一个运行时常量池都分配在Java虚拟机的方法区中,在类和接口被加载到虚拟机后,对应的运行时常量池就被创建处理。
class文件中的常量池:
class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。
字面量(文本字符串、声明为final的常量值…)
符号引用量(类和接口的权限定名、字段名称和描述符、方法名和描述符)
类初始化时机
1,用new关键字实例化对象的时候;
读取或设置一个类的静态字段(被final修饰,已在编译器把结果放入常量池的静态字段除外)的时候;
调用一个类的静态方法的时候。
2) 使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
3)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
4)当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
5) 当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化。
类的实例化与类的初始化是两个不同的概念:
类的实例化是指创建一个类的实例(对象)的过程;
类的初始化是指为类中各个类成员(被static修饰的成员变量)赋初始值的过程,是类生命周期中的一个阶段。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)