1. 什么是类?什么是对象?
-
现实生活中是由很多很多对象组成的,基于对象抽出了类
-
对象:软件中真实存在的单个个体/东西
- 类:类别/类型,代表一类个体
-
类是对象的模子,对象是类的具体的实例
-
类中可以包含:
- 对象的属性/特征-----------------------成员变量
- 对象的行为/动作-----------------------方法
-
一个类可以创建多个对象
2. 如何创建类?如何创建对象?如何访问成员?
public class Student { //Student类就是我们自己造的一种引用类型
//成员变量
String name;
int age;
String address;
//方法
void study(){
System.out.println(name+"在学习...");
}
void sayHi(){
System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address);
}
}
public class StudentTest {
public static void main(String[] args){
//创建一个学生对象
Student zs = new Student();
//给成员变量赋值
zs.name = "zhangsan";
zs.age = 25;
zs.address = "河北廊坊";
//调用方法
zs.study();
zs.sayHi();
Student ls = new Student();
ls.name = "lisi";
ls.age = 24;
ls.address = "黑龙江佳木斯";
ls.study();
ls.sayHi();
//1)创建了一个学生对象
//2)给所有成员变量赋默认值
Student ww = new Student();
ww.study();
ww.sayHi();
}
}
3. 方法的重载(overload/overloading)
------------更加方便用户的访问
- 发生在同一类或父子类中,方法名相同,参数列表不同
- 编译器在编译时会根据方法的签名自动绑定方法
//重载的演示
public class OverloadDemo {
public static void main(String[] args) {
Aoo o = new Aoo();
o.show(); //编译器根据方法的签名自动绑定方法
o.show("zhangsan");
o.show(25);
o.show("zhangsan",25);
o.show(25,"zhangsan");
}
}
class Aoo{
void show(){}
void show(String name){}
void show(int age){}
void show(String name,int age){}
void show(int age,String name){}
//int show(){ return 1;} //编译错误,重载与返回值类型无关
//void show(String address){} //编译错误,重载与参数名称无关
}
补充:
-
高质量的代码:---------------------以后的目标、拿年薪
-复用性好、扩展性好、维护性好、可移植性好\健壮性好、可读性好、效率好…
-
默认值规则:
byte,short,int,char------------0 long---------------------------0L double------------------------0.0 float-------------------------0.0f boolean-----------------------false 引用类型-----------------------null
-
//若想访问对象,需要通过引用zs 引用 数据类型 引用类型变量 指向 对象 Student zs = new Student();
-
方法的签名:方法名+参数列表
4. 构造方法:构造函数、构造器、构建器
---------------复用给成员变量赋初值代码
- 作用:给成员变量赋初始值
- 与类同名,没有返回值类型(连void都没有)
- 在创建(new)对象时被自动调用
- 若自己不写构造方法,则编译器默认提供一个无参构造方法,若自己写了构造方法,则不再默认提供(若引用对象的数据可以写死,则可以在new对象时直接传参:Student zs=new Student(“ZS”,20,“LF”))
- 构造方法可以重载
5. this
---------指代当前对象,哪个对象调用方法它指的就是哪个对象
zs.study()-----------this.指代zs
只能用于实例方法或构造方法中
只能用在方法中,方法中访问成员变量之前默认有个this.
this的用法:
-
this.成员变量名-------------访问成员变量
成员变量与局部变量同名时,若想访问成员变量则this不能省略
class Student { String name; //成员变量(整个类中) int age; String address; //局部变量(当前方法中) Student(String name,int age,String address){ this.name = name; this.age = age; this.address = address; } void study(){ System.out.println(name+"在学习..."); } void sayHi(){ System.out.println("大家好,我叫"+name+",今 年"+age+"岁了,家住"+address); } }
-
this.方法名()-----------------调用方法(了解)
-
this()---------------------------调用构造方法(了解)
6. null
----------表示空,没有指向任何对象,若引用的值为null,则该引用不能进行任何点操作了,若操作则发生NullPointerException空指针异常
7. 引用类型数组
1)Bomb[] bs = new Bomb[3];
bs[0] = new Bomb(100,200); //**1)给元素赋值需要去new个对象**
bs[1] = new Bomb(200,300);
bs[2] = new Bomb(220,330);
//**2)若想访问对象的数据,需要通过数组元素去打点**
bs[0].x = 111; //给第1个炸弹的x修改为111
System.out.println(bs[1].width); //输出第2个炸弹的宽
bs[2].move(); //第3个炸弹移动
1)Bomb[] bs = new Bomb[3];
bs[0] = new Bomb(100,200);
bs[1] = new Bomb(200,300);
bs[2] = new Bomb(300,400);
System.out.println(bs[0].width); //输出第1个炸弹的宽
bs[1].x = 250; //修改第2个炸弹的x为250
bs[2].move(); //第3个炸弹移动
for(int i=0;i<bs.length;i++){ //遍历所有子弹
System.out.println(bs[i].height); //输出每个子弹的高
bs[i].move(); //每个子弹移动
}
2)Bomb[] bs = new Bomb[]{ //了解
new Bomb(100,200),
new Bomb(200,300),
new Bomb(300,400)
};
补充:
-
成员变量:写在类中,方法外--------有默认值
局部变量:方法中------------------------没有默认值
-
java规定:成员变量和局部变量是可以同名的
使用的时候默认采取的是就近原则
-
数组也是一个对象,所以数组对象也存储在堆中,
将数组的元素当作成员变量一并存储在堆中
- 基本类型数组和引用类型数组的区别:
1.赋值:
(1)基本类型数组:通过下标直接给元素赋值
int[] a=new int[3];a[0]=6;
(2)引用类型数组:要给元素赋值需要去new个对象
Student[] stus=new Student[10]; stus[0]=new Student(有参传参)
2.访问:
(1)基本类型数组:通过下标访问元素
System.out.println(a[0]);
(2)引用数组类型:若想访问对象的数据,需要通过数组元素去打点
System.out.println(stus[0].name);
8. 继承
-
作用:代码复用
-
通过extends来实现继承
-
超类/父类:共有的属性和行为
派生类/子类:特有的属性和行为
-
派生类既能访问自己的,也能访问超类的,但超类不能访问派生类的
-
一个超类可以有多个派生类
一个派生类只能有一个超类-----------单一继承
-
具有传递性
-
继承要符合is a(是一个)的关系
9. super
---------------指代当前对象的超类对象
super的用法:
(只能点出来普通方法)
-
super.成员变量名----------------------访问超类的成员变量(了解)
-
super.方法名()---------------------------调用超类的方法
-
super()-------------------------------------调用超类的构造方
-
java规定:构造派生类之前必须先构造超类
- 派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法
- 派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供
super()调用超类构造方法,必须位于派生类构造方法的第一行
//super的演示 public class SuperDemo { public static void main(String[] args) { Boo o = new Boo(); } } class Coo{ Coo(int a){ } } class Doo extends Coo{ Doo(){ super(5); //调用超类的有参构造 } /* //如下代码为默认的: Doo(){ super(); } */ } class Aoo{ Aoo(){ System.out.println("超类构造"); } } class Boo extends Aoo{ Boo(){ //super(); //默认的,调用超类的无参构造 System.out.println("派生类构造"); } }
10. 向上造型
---------------------代码复用
- 超类型的引用指向了派生类的对象
- 能点出来什么,看引用的类型
package ooday03;
//向上造型的演示
public class UploadDemo {
public static void main(String[] args) {
Eoo o1 = new Eoo();
o1.a = 1;
o1.show();
//o1.b = 2; //编译错误
//o1.test(); //编译错误,超类不能访问派生类的
Foo o2 = new Foo();
o2.b = 1;
o2.test();
o2.a = 2; //正确
o2.show(); //正确,派生类可以访问超类的
Eoo o3 = new Foo(); //向上造型
o3.a = 1;
o3.show();
//o3.b = 2; //编译错误
//o3.test(); //编译错误,能点出来什么,看引用的类型
}
}
class Eoo{
int a;
void show(){
}
}
class Foo extends Eoo{
int b;
void test(){
}
}
补充:
- 继承意味着代码虽然我没有写,但也属于我,只是没有写在一起而已
- 泛化:将共有的抽出来的过程,泛化是设计层面的概念,从代码实现层面来说咱们就是继承,泛化就是继承
11. 方法的重写(override/overriding)
重新写、覆盖
- 发生在父子类中,方法名相同,参数列表相同
- 重写方法被调用时,看对象的类型
- 派生类不能重写超类中的static方法
当派生类觉得超类的行为不够好时,可以重写
我继承了一个中餐馆
class Aoo{
void do(){
做中餐
}
}
A:我还是想做中餐------------不需要重写
class Boo extends Aoo{
}
B:我想改做西餐--------------需要重写
class Boo extends Aoo{
void do(){
做西餐
}
}
C:我想在中餐基础之上加西餐-----需要重写(先super中餐,再加入西餐)
class Boo extends Aoo{
void do(){
super.do();
做西餐
}
}
12. 重写与重载的区别
-
重写:发生在父子类中,方法名相同,参数列表相同
一般用于在派生类中修改超类的方法
-
重载:发生在同一类中,方法名相同,参数列表不同
是完全不同的方法,只是方法名相同而已
13. package和import
-
package:声明包
- 作用:避免类的命名冲突
- 同包中的类不能同名,不同包中的类可以同名
- 类的全称:包名.类名,包名常常有层次结构
- 建议:包名所有字母都小写
说明:package声明包必须位于第一行
-
import:导入类
- 同包中的类可以直接访问,不同包的类不能直接访问,若想访问:
- 先import导入类,再访问类----------建议
- 类的全称-----------------------------------太繁琐,不建议
说明:import导入类必须位于声明包的下一行
- 同包中的类可以直接访问,不同包的类不能直接访问,若想访问:
14. 访问控制修饰符
封装的意义:隐藏一些东西,暴露一些东西,来保护数据的安全
- public:公开的,任何类-------(方法)
- protected:受保护的,本类、同包类、派生类
- 默认的:什么也不写,本类、同包类
- private:私有的,本类--------(成员变量)
- 类的访问权限只能是public或默认的
- 类中成员的访问权限如上四种都可以
//封装的意义
class Card{
private String cardId;
private String cardPwd;
private double balance;
public boolean payMoney(double money){ //支付金额
if(balance>=money){
balance-=money;
return true;
}else{
return false;
}
}
public boolean checkPwd(String pwd){ //检测密码
if(pwd与cardPwd相同){
return true;
}else{
return false;
}
}
}
//访问权限范围:
package ooday04;
//演示访问控制修饰符
public class Aoo {
public int a; //任何类
protected int b; //本类、派生类、同包类
int c; //本类、同包类
private int d; //本类
void show(){
a = 1;
b = 2;
c = 3;
d = 4;
}
}
class Boo{ //---------------演示private
void show(){
Aoo o = new Aoo();
o.a = 1;
o.b = 2;
o.c = 3;
//o.d = 4; //编译错误
}
}
package ooday04_vis;
import ooday04.Aoo;
public class Coo { //演示同包的概念
void show(){
Aoo o = new Aoo();
o.a = 1;
//o.b = 2; //编译错误
//o.c = 3; //编译错误
//o.d = 4; //编译错误
}
}
class Doo extends Aoo{ //演示protected
void show(){
a = 1;
b = 2;
//c = 3; //编译错误
//d = 4; //编译错误
}
}
15. static:静态的
-
静态变量:
- 由static修饰
- 属于类,存储在方法区中,只有一份
- 常常通过类名点来访问,也可以通过对象名打点来使用
- 何时用:所有对象所共享的数据(图片、音频、视频等)
public class StaticDemo { public static void main(String[] args) { Eoo o1 = new Eoo(); o1.show(); Eoo o2 = new Eoo(); o2.show(); Eoo o3 = new Eoo(); o3.show(); System.out.println(Eoo.b); //常常通过类名点来访问 } } class Eoo{ //演示静态变量 int a; static int b; Eoo(){ a++; b++; } void show(){ System.out.println("a="+a+",b="+b); } }
-
静态方法:
- 由static修饰
- 属于类,存储在方法区中,只有一份
- 常常通过类名点来访问,也可以通过对象名打点来使用
- 静态方法没有隐式this传递,所以不能直接访问实例成员
- 何时用:方法的操作与对象无关
//static的演示 public class StaticDemo { public static void main(String[] args) { Goo.plus(4,6); } } //演示静态方法 class Foo{ int a; //实例变量(由对象来访问) static int b; //静态变量(由类名来访问) void show(){ //有隐式this System.out.println(this.a); System.out.println(Foo.b); } static void test(){ //静态方法中没有隐式this传递 //没有this就意味着没有对象 //而实例变量a是必须由对象来访问的 //所以下面的语句发生编译错误 //System.out.println(a); //编译错误 System.out.println(Eoo.b); } } //演示静态方法何时用 class Goo{ int a; //对象的属性 //方法中用到了对象的属性a,意味着show()的操作与对象是有关的,不能做成静态方法 void show(){ System.out.println(a); } //方法中没有用到对象的属性和行为,意味着plus()的操作与对象是无关的,可以做成静态方法 static void plus(int num1,int num2){ int num = num1+num2; System.out.println(num); } }
-
静态块:
- 由static修饰
- 属于类,在类被加载期间自动执行,一个类只被加载一次,所以静态块也只执行一次
- 何时用:初始化/加载静态资源(图片、音频、视频等)
public class StaticDemo { public static void main(String[] args) { Hoo o4 = new Hoo(); Hoo o5 = new Hoo(); Hoo o6 = new Hoo(); } } //演示静态块 class Hoo{ static { System.out.println("静态块"); } Hoo(){ System.out.println("构造方法"); } }
补充:
-
在构造方法中给实例变量做初始化
-
在静态块中给静态变量做初始化
执行顺序:父类静态块–>子类静态块–>父类非静态块–>父类构造方法–>子类非静态块–>子类构造方法
16.重写方法原则-------两同、两小、一大
两同:方法名名和参数列表相同
两小:
- 派生类方法抛出异常必须小于或等于超类;
- 派生类方法的返回值类型必须小于或等于超类;
void/基本类型:必须相等
引用类型:必须小于或等于
一大: 派生类方法的访问权限必须大于或等于超类
补充:
- 成员变量分两种:
-
实例变量:没有static修饰,属于对象的,存储在堆中,
有几个对象就有几份,通过引用打点来访问
-
静态变量:有static修饰,属于类的,存储在方法区中,
只有一份,通过类名打点来访问
17. final:最终的,不可改变的
----------单独应用几率低
-
修饰变量:变量不能被改变
//演示final修饰变量 class Aoo{ final int num = 5; void show(){ //num = 55; //编译错误,final的变量不能被改变 } }
-
修饰方法:方法不能被重写
//演示final修饰方法 class Boo{ final void show(){} } class Coo extends Boo{ //void show(){} //编译错误,final修饰的方法不能被重写 }
-
修饰类:类不能被继承
//演示final修饰类 final class Doo{} //class Eoo extends Doo{} //编译错误,final的类不能被继承 class Foo{} final class Goo extends Foo{} //不能当老爸,但能当儿子
18. static final常量
---------------应用率高
- 必须声明同时初始化
- 通过类名点来访问,不能被改变
- 建议:常量名所有字母都大写,多个单词用_分隔
- 编译器在编译时会将常量直接替换为具体的值,效率高
- 何时用:数据永远不变,并且经常使用
public class StaticFinalDemo {
public static void main(String[] args) {
System.out.println(Hoo.PI); //通过类名点来访问
//Hoo.PI = 3.1415926; //编译错误,常量不能被改变
//1)加载Ioo.class到方法区中
//2)将静态变量num一并存储到方法区中
//3)到方法区中获取num的值并输出
System.out.println(Ioo.num);
//编译器在编译时将常量直接替换为具体的值,效率高
//相当于System.out.println(5);
System.out.println(Ioo.COUNT);
}
}
class Ioo{
public static int num = 5; //静态变量
public static final int COUNT = 5; //常量
}
class Hoo{
public static final double PI = 3.14159;
//public static final int NUM; //编译错误,常量必须声明同时初始化
}
19. 抽象方法
- 由abstract修饰
- 只有方法的定义,没有具体的实现(连{}都没有)
抽象类:
-
由abstract修饰
-
包含抽象方法的类必须是抽象类
-
抽象类不能被实例化(new对象)
-
抽象类是需要被继承的,派生类:
- 重写所有抽象方法--------------变不完整为完整
- 也声明为抽象类------------------一般不这么做
抽象类的意义:
封装共有的属性和行为--------------------代码复用
为所有派生类提供统一的类型-----------向上造型—代码复用
可以包含抽象方法,为所有派生类提供统一的入口(能点出来)
派生类的行为不同,但入口是一致的,同时相当于定义了一个标准
补充:
抽象方法/抽象类的疑问:
-
抽象方法的存在意义是什么?
- 保证当发生向上造型时,通过超类型的引用能点出来那个方法
-
既然意义只在于能点出来,那为什么不设计为普通方法?
- 若设计为普通方法,则派生类可以重写也可以不重写,而设计为抽象方法,可以强制派生类必须重写------做了个标准,强制必须重写
20.成员内部类
------------应用率低,了解
- 类中套类,外面的称为外部类,里面的称为内部类
- 内部类通常只服务于外部类,对外不具备可见性
- 内部类对象只能在外部类中创建
- 内部类中可以直接访问外部类的成员(包括私有的),在内部类中有个隐式的引用指向了创建它的外部类对象------外部类名.this
public class InnerClassDemo {
public static void main(String[] args) {
Mama m = new Mama();
//Baby b = new Baby(); //编译错误,内部类对外不具备可见性
}
}
class Mama{ //外部类
private String name;
Baby b = new Baby(); //内部类对象通常在外部类中创建
class Baby{ //内部类
void show(){
System.out.println(name);
System.out.println(Mama.this.name); //Mama.this指代它的外部类对象
}
}
}
21. 匿名内部类
- 若想创建一个类的派生类对象,并且对象只创建一个(一次),此时该类(派生类)不必命名,称为匿名内部类
- 匿名内部类中不能修改外面变量的值,也不能访问在外面被修改过的变量,因为在此处该变量默认为final的
public class AnonInnerClassDemo {
public static void main(String[] args) {
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o1
//3)大括号中的为派生类的类体
Aoo o1 = new Aoo(){
};
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o2
//3)大括号中的为派生类的类体
Aoo o2 = new Aoo(){
};
int num = 5;
num = 55;
//1)创建了Boo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o3
//3)大括号中的为派生类的类体
Boo o3 = new Boo(){
void show(){
System.out.println("showshow");
//num = 66; //编译错误,匿名内部类中不能修饰外面变量的值,因为在此处默认为final的
}
};
o3.show();
}
}
abstract class Boo{
abstract void show();
}
abstract class Aoo{
}
补充:
-
隐式对象:
- this:当前对象
- super:当前对象的超类对象
- 外部类名.this:当前对象的外部类对象
- 匿名内部类不能修改外面变量的值,因为在此处默认为final的
-
小面试题:
-
问:内部类有独立的.class字节码文件吗?
答:有
-
-
做功能的套路:
- 先写行为/方法:
- 若为某对象所特有的行为,就将方法设计在特定的类中
- 若为所有对象所共有的行为,就将方法设计在超类中
- 窗口调用:
- 若为定时发生的,就在定时器中调用
- 若为事件触发的,就在侦听器中调用----------明天上午讲
- 先写行为/方法:
-
调错方式:
- 打桩:System.out.println(数据);
22. 接口
-
是一种引用数据类型
-
由interface定义
-
只能包含常量和抽象方法------默认权限是public
接口不能被实例化
接口是需要被实现/继承,实现/派生类:必须重写所有抽象方法
一个类可以实现多个接口,用逗号分隔,
若又继承又实现时,应先继承后实现
接口可以继承接口
接口的意义:
- 封装部分派生类共有的属性和行为,实现多继承
- 制定了一个标准,一种规范
public class InterfaceDemo {
public static void main(String[] args) {
//Inter o = new Inter(); //编译错误,接口不能被实例化
Inter5 o1 = new Doo(); //向上造型
Inter4 o2 = new Doo(); //向上造型
}
}
//演示接口的定义
interface Inter{
public static final int NUM = 5;
public abstract void show();
int COUNT = 5; //默认public static final //接口中的成员默认访问权限是public
void test(); //默认public abstract
//int number; //编译错误,常量必须声明同时初始化
//void say(){} //编译错误,抽象方法不能有方法体
}
//演示接口的定义
interface Inter{
public static final int NUM = 5;
public abstract void show();
int COUNT = 5; //默认public static final //接口中的成员默认访问权限是public
void test(); //默认public abstract
//int number; //编译错误,常量必须声明同时初始化
//void say(){} //编译错误,抽象方法不能有方法体
}
//演示接口的实现
interface Inter1{
void show();
void test();
}
class Aoo implements Inter1{
public void show(){} //重写接口中的抽象方法时,访问权限必须设计为public的
public void test(){}
}
//演示接口的多实现
interface Inter2{
void show();
}
interface Inter3{
void test();
}
abstract class Boo{
abstract void say();
}
class Coo extends Boo implements Inter2,Inter3{
public void show(){}
public void test(){}
void say(){}
}
//演示接口继承接口
interface Inter4{
void show();
}
interface Inter5 extends Inter4{
void test();
}
class Doo implements Inter5{
public void test(){}
public void show(){}
}
补充:
-
类和类------------------------继承extends
接口和接口------------------继承extends
类和接口---------------------实现implements
-
设计规则:
-
将所有派生类所共有的属性和行为,抽到超类中-------------抽共性
-
派生类的行为都一样,则设计为普通方法
派生类的行为不一样,则设计为抽象方法
-
将部分派生类所共有的属性和行为,抽到接口中
接口是对继承的单根性的扩展---------------实现多继承
符合既是也是原则时,应使用接口
-
-
可以向上造型为:超类+所实现的接口
23. 多态
表现:
-
同一个对象被造型为不同的类型时,有不同的功能
– 对象的多态:我、你、水…------所有对象都是多态的
同一类型的引用指向不同的对象时,有不同的实现
–行为的多态:cut(),move(),getImage()–所有抽象方法都是多态的
向上造型/自动类型转换:--------------------代码复用
- 超类型的引用指向派生类的对象
- 能点出来什么,看引用的类型
- 能造型成为的数据类型有:超类+所实现的接口
强制类型转换,成功的条件只有如下两种:
引用所指向的对象,就是该类型
引用所指向的对象,实现了该接口或继承了该类
强转时若不符合如上条件,则发生ClassCastException类型转换异常
建议:在强转之前先通过instanceof来判断引用的对象是否是该类型
public class MultiTypeDemo {
public static void main(String[] args) {
Aoo o = new Boo();
Boo o1 = (Boo)o; //引用o所指向的对象,就是Boo类型
Inter o2 = (Inter)o; //引用o所指向的对象,实现了Inter接口
//Coo o3 = (Coo)o; //运行时ClassCastException类型转换异常
if(o instanceof Coo){ //false
Coo o4 = (Coo)o;
}else{
System.out.println("o不是Coo类型");
}
/*
System.out.println(o instanceof Boo); //true
System.out.println(o instanceof Inter); //true
System.out.println(o instanceof Coo); //false
*/
}
}
interface Inter{ }
class Aoo{ }
class Boo extends Aoo implements Inter{ }
class Coo extends Aoo{ }
补充:
-
接口可以继承多个接口:
interface Inter1{ void show(); } interface Inter2{ void test(); } interface Inter3 extends Inter1,Inter2{ void say(); }
-
何时需要强转?
想访问的属性/行为在超类中没有,必须强转,强转之前先instanceof判断
-
ArrayIndexOutOfBoundsException:数组下标越界异常
NullPointerException:空指针异常
ClassCastException:类型转换异常
4.碰撞检测
24.内存管理:由JVM管理的
-
堆:
-
存储new出来的对象(包括实例变量)
-
垃圾:没有任何引用所指向的对象
垃圾回收器(GC)不定时到内存堆中清扫垃圾,回收的过程中透明的(看不到的),不一定一发现垃圾就立刻回收,通过调用System.gc()建议虚拟机尽快调度GC来回收
-
实例变量的生命周期:
创建对象时存储在堆中,对象被回收时一并被回收
-
内存泄漏:不再使用的对象没有被及时的回收,严重的泄漏会导致系统的崩溃,建议:不再使用的对象应及时将引用设置为null
-
-
栈:
-
存储正在调用的方法中的局部变量(包括方法的参数)
(如果局部变量为基本类型,则栈中的局部变量存储数字;如果局部变量为引用类型,则栈中的局部变量存储地址) -
调用方法时,会为该方法在栈中分配一块对应的栈帧,栈帧中存储局部变量(包括方法的参数),方法调用结束时,栈帧被自动清除,局部变量一并被清除。
-
局部变量的生命周期:
调用方法时存储在栈中,方法调用结束时与栈帧一并被清除
-
-
方法区:
- 存储.class字节码文件(包括静态变量、所有方法)
- 方法只有一份,通过this来区分具体的调用对象
25.面向对象三大特征总结
1.封装:
- 类:封装对象的属性和行为
- 方法:封装的是具体的业务逻辑实现- 访问控制修饰符:封装的是具体的访问权限
2.继承:
-
作用:代码复用
-
超类:所有派生类所共有的属性和行为
接口:部分派生类所共有的属性和行为
派生/实现类:派生类所特有的属性和行为
-
单一继承、多接口实现,具有传递性
3 多态:
-
行为多态:所有抽象方法都是多态的(通过重写来表现)
-
对象多态:所有对象都是多态的(通过向上造型为表现)
- 重写、向上造型、强制类型转换(instanceof判断)
26.补充
- 实例变量和局部变量的区别:
- 实例变量:
- 写在类中、方法外
- 创建对象时存储在堆中,对象被回收时一并被回收
- 有默认值
- 局部变量:
- 写在方法中
- 调用方法时存储在栈中,方法调用结束时与栈帧一并被清除
- 没有默认值
Aoo o = new Aoo();-------------a=0
o.show(5);---------------------b=5
class Aoo{
int a;
void show(int b){
int c;
System.out.println(a); //0
System.out.println(b); //5
System.out.println(c); //发生编译错误
}
}
2.面试题:
- 问:java是值传递还是引用传递?
- 答:java只有值传递,基本类型传递的是具体的数,引用类型传递的是具体的地址
3.文档注释:
- 为功能性注释,只在三个地方使用,分别是类上、方法上和常量上
//文档注释是功能性注释,只在三个地方使用,分别是类上、方法上和常量上
/**
* 在类上使用时用于说明当前类的设计目的和整体功能介绍
* 例如: 此类用于演示java文档注释
*
* @author 作者WKJ
*/
public class ApiDocDemo {
/**
* sayHi方法中使用的问候语
*/
public static final String INFO = "你好!";
/**
* 为指定用户添加问候语
* @param name 指定用户的名字
* @return 含有问候语的字符串
*/
public String sayHi(String name){
return INFO+name;
}
}
-
getter/setter:
class Student{ private String name; private int age; public String getName(){ //getter获取 return name; } public void setName(String name){ //setter设置 this.name = name; } public int getAge(){ //getter获取 return age; } public void setAge(int age){ //setter设置 this.age = age; } } //getter和setter的演示 public class GetterSetterDemo { public static void main(String[] args) { Student zs = new Student(); zs.setName("zhangsan"); zs.setAge(25); System.out.println(zs.getName()); System.out.println(zs.getAge()); Student ls = new Student(); ls.setName("lisi"); ls.setAge(24); System.out.println(ls.getName()); System.out.println(ls.getAge()); } }
5.引用类型赋值