堆可以动态的分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈的存取速度的比堆要快,仅次于直接位于CPU中的寄存器。堆由于要在运行时动态分配内存,存取速度较慢
---------------------------------------------------------------------------------------------------------------------------------
OOP优点:
1、代码开发模块化,更易维护和修改
2、代码复用
3、增强代码的可靠性和灵活性
4、增加代码的可理解性
OOP特性:封装(关注对象行为的细节)、
继承、
多态、
抽象(关注对象的行为)
封装好处:
1、通过隐藏对象的属性来保护对象内部的状态
2、提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩 展
3、禁止对象之间的不良交互提高模块化
继承:
继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用性,也可以在不修改类的情况下给现存的类添加新特性。
--------------------------------------------------------------------------------------------
成员变量:
1)类中、方法外
2)创建对象时被存储在堆中,对象被回收时一并被回收
3)有默认值
成员变量:
1)实例成员变量:没有static修饰,属于对象的,存在堆中,
有几个对象就有几份
常常通过对象名点来访问
2)静态成员变量:由static修饰,属于类的,存在方法区中,
常常通过类名点来访问
不属于对象的数据结构
不用初始化便可调用,默认值基本类型为0,引用为null
-------------------------------------------------------------------------------
局部变量: 不能加任何修饰符
1)方法中
2)调用方法时被存储在栈中,方法结束时与栈帧一并被清除
3)没有默认值
---------------------------------------------------------------------------------
一个类中不能定义两个public
------------------------------------------------------------------------------------------
Point p = new Point()
类 引用(栈) 对象(堆)
Emp emp =newEmp();
emp.name=“黄河大侠”; //访问对象的成员变量
JFrame frame =new JFrame();
frame.setSize(200,300); //调用方法
--------------------------------------------------------------------------------------------
基本类型 八个基本类型
-------------------------------------
引用类型: 类
接口
数组
--------------------------------------------------------------------------------------------
基本类型变量直接存储在栈中
引用类型变量存储的是对象的地址信息,
引用类型变量存储在栈中,
但对象存储在堆中
------------------------------------------------------------------------------------------------
类的各种信息在方法区中保存
数组对象在堆中存储,数组变量属于引用类型,存储数组对象的地址信息,指向数组对象
------------------------------------------------------------------------------------------------
对引用类型变量的赋值:
1、new
2、相同类型的引用变量之间的相互赋值
案例:
Emp e1 = new Emp();
Emp e2 = e1; //将e1的值(对象的地址信息)赋给e2,e2和e1指向相同的对象。
e1.name =“m1”;
e2.name = “m2”;
System.out.println(e1.name);
attention!!!但是引用类型变量之间的赋值不会创建新的对象,但有可能会使两个以上的引用指向同一个对象
案例:
Empt m1 = new Empt();
Emptm2 = m1;
m1.name= "m1";
m2.name = "m2";
System.out.println(m1.name);
System.out.println(m2.name);
输出:
m1.name:m2
m2.name:m2
------------------------------------------------------------------------------------------------
3、赋值为null,即还没有指向任何对象
Emp emp =null; //引用emp中的值为null,没有指向任何对象;
emp = newEmp(); //引用emp指向了一个Emp对象;
attention!!!当一个引用的值为null的时候,如果通过引用访问对象成员变量或者调用方法时不合逻辑的(因为没有指向某对象,自然不会有属性和方法),此时会产生NullPointException
------------------------------------------------------------------------------------------------
Java的基本数据类型是传值调用,对象是传引用地址,String特殊,并不会改变
传值时,改变形参的值,并不改变实参的值
传地址时,如果参数是对象,无论对对象做何种操作,都不改变实参对象的引用,
但如果改变对象的内容,就会改变实参对象的内容
------------------------------------------------------------------------------------------------
方法可以与类名相同,但不建议
------------------------------------------------------------------------------------------------
在类方法中不能有this关键字 static方法
在类方法中调用本来的类方法可以直接调用
类方法指的是类中用static修饰的方法(非static为实例方法),
比如main方法那么可以以main方法为例,直接调用其他类方法。
必须通过实例调用实例方法。
------------------------------------------------------------------------------------------------
#### 构造方法
定义:
构造方法的定义:
1、构造方法的名称必须与类名相同
2、构造方法没有返回值,但也不能写void
* 一个类可以定义多个构造方法,方法名都与类名相同,参数不同,即为重载
------------------------------------------------------------------------------------------------
父类有有参构造器,则子类必须也有相同参数的有参构造器,且第一行super(参数)继承父
类构造器
attention!!!子类不能继承父类的构造方法
父类若不定义构造器则系统默认会定义一个无参构造器,
子类构造器中默认又super调用父类构造器
所以向上造型会先调用父类构造,再调用子类构造
父静,子静,父构块,父构法,子构块,子构法
但是若定义了一个构造器,则系统就不会做了
即若父类只定义了一个有参构造器,那么父类就只有这一个有参构造器就没有无参构造器
------------------------------------------------------------------------------------------------
###内存管理
内存管理:由JVM来管理---------了解
1)堆:
1.1)存储所有new出来的对象(包括成员变量)
1.2)垃圾:没有任何引用所指向的对象
垃圾回收器(GC)不定时到内存中清扫垃圾,
回收过程是透明的,并不一定一发现垃圾,则立即回收,
调用System.gc()可以建议JVM尽快调度GC来回收垃圾
1.3)内存泄漏:不再使用的内存还没有被及时的回收
严重的泄漏会导致系统的崩溃
建议:对象不再使用时及时将引用设置为null
1.4)成员变量的生命周期:
创建对象时被存储在堆中,对象被回收时一并被回收
2)栈:
2.1)存储正在调用的方法中的所有局部变量(包括参数)
2.2)调用方法时在栈中为该方法分配一块对应的栈帧,
栈帧中存储方法的局部变量以及参数,
方法执行结束则栈帧被清除,局部变量一并被清除
2.3)局部变量的生命周期:
调用方法时被存储在栈中,方法结束时与栈帧一并被清除
3)方法区:
3.1)用于存储.class字节码文件(包括方法)
3.2)方法只有一份,通过this来区分具体的对象
Java中静态属性和静态方法可以被继承,但是没有被重写而是被隐藏,重写后的静态方法不支持多态,即静态方法被重写时,调用次方法看的是引用类型
子类继承父类的属性和方法
但是成员变量是没有重写的,成员变量可以被继承,但是不能构成多态
静态变量和静态常量属于类,不属于对象,因此不能被覆盖
------------------------------------------------------------------------------------------------
######### 向上造型
父类型的引用指向子类的对象
属性的值取父类还是子类并不取决于我们创建对象的类型,而是取决于我们定义的变量的类型
能点出来什么看引用的类型(即父类成员变量,方法之类)
但是
如果子类重写了父类的方法,那么点出来的就是子类的方法
BUT,
如果子类没有重写父类的方法,那么点出来的方法还是父类的
BUT
如果这个方法静态方法,就看定义的类型是谁
强制类型转换:大到小
强制类型转换看new出来的对象而非引用类型
Father f = new Son();
X x = ( X ) f;
这个X一定要比Son大,否则ClassCastExction
当然X和( X )可以不一样,只要X >= ( X ) >= Son就好了
但是不管类型如何转换,能点出来的方法都是看new出来的对象
用super可以访问被隐藏的静态方法和属性
------------------------------------------------------------------------------------------------
一个很有趣的现象
因为子类默认继承父类的成员变量和方法
所以多次继承中若new出来的对象没有重写方法,则调用的是上一级的重写方法
------------------------------------------------------------------------------------------------
class AA {}
class BB extends AA {} AA c =new CC();
class CC extends BB {} AAa = (AA) c;// ok
class DD extends CC {} BB b = (BB) c;// ok
BB b = new CC(); CCc = (CC) c;// ok
AA a = (AA)b;//ok DDd = (DD) c;// CastException
CC c = (CC)b;//ok
DD d = (DD)b;//CastException
------------------------------------------------------------------------------------------------
访问控制修饰符:
1)public:公开的,任何类
2)private:私有的,本类
3)protected:受保护的,本类、子类、同包类
4)默认的:什么也不写,本类、同包类
外部类and接口的访问修饰符只能是public和默认的(default可以写出来,但是编译之后自动转换为了public )
抽象类、接口也不能用protected和private
因为接口可以让所有的类去实现(非继承),不只是其子类
protected和private可以修饰内部类
private < default < protected <public
------------------------------------------------------------------------------------------------
static:静态的
1)静态变量:
1.1)由static修饰
1.2)属于类的,存在方法区中,只有一份
1.3)常常通过类名点来访问
1.4)何时用:所有对象所共享的数据(图片、音频、视频等)
2)静态方法:
2.1)由static修饰
同一个类可以直接调
不同类用类名.来调
2.2)属于类的,存在方法区中,只有一份
2.3)常常通过类名点来访问
也可以用实例来点
2.4)没有隐式的this传递,
所以在静态方法中不能直接访问实例成员变量
2.5)何时用:方法的操作仅与参数相关而与对象无关
在静态方法中不可用this掉本类中的静态方法
静态方法不可以直接操作外部的非静态对象/非静态方法
用实例对象访问,可直接操作同类静态方法
子类继承重写父类是静态方法只是隐藏并没有覆盖
向上造型点出来的还是父类的静态方法
强转为子类还是如此
3)静态块:
3.1)由static修饰
所以静态块也只执行一次
3.3)何时用:加载/初始化静态资源(图片、音频、视频等)
注:先执行static块,再执行构造方法,多个静态块从上往下执行
------------------------------------------------------------------------------------------------
final:最终的、不可改变的
1)修饰变量:变量不能被改变 类中成员变量final修饰可以不赋初值,但是构造器中一定要赋值并且之后不能再改变
2)修饰方法:方法不能被重写,可以重载
3)修饰类:类不能被继承
如果final修饰的是对象,则对象地址不可以改变,但其值可以改变
------------------------------------------------------------------------------------------------
static final常量:
1)必须声明同时初始化
2)通过类名点来访问,不能被改变
3)建议:常量名所有字母都大写,多个单词用_分隔
4)编译器在编译时常量被直接替换为具体的值,效率高
------------------------------------------------------------------------------------------------
抽象方法不可以是静态的,不可以有方法体,不可以在普通类中定义,但可以在接口和抽象类中定义
abstract可以修饰方法和类,但是不能修饰属性、字段。
抽象方法没有方法体即没有大括号,不可以写出大括号
------------------------------------------------------------------------------------------------
### 抽象类:
抽象类只能用public和默认的修饰
但是抽象方法可以用public、默认的和protected
1)由abstract修饰
2)包含抽象方法的类必须是抽象类
不包含抽象方法的类也可以声明为抽象类---我乐意
3)抽象类不能被实例化
抽象方法不能由private,static,synchronized,native修饰
static修饰的方法可以通过类名来访问该方法(即方法体),抽象方法用static没有意义
抽象类可以有构造方法(向上造型子类构造器默认super父类构造器)
------------------------------------------------------------------------------------------------
### 接口: 一个接口可以继承多个接口,因为接口不是类
接口继承接口不用实现父类接口的方法
因为接口中不包含任何实现,所以与存储空间没有任何关系
接口是一种数据类型(引用类型)
·接口只能用public和默认 的修饰
·且接口内的抽象方法只能用public
·接口不能被实例化
·接口的访问控制修饰符只能是public和默认的
·若又继承又实现时,应先继承后实现
·接口是完全抽象的抽象类
·只包含常量和抽象方法 普通方法加default
int i = 1;等价于public static final inti = 1;
里面的方法全是抽象方法
void method();同理也等价于 public abstarctvoid method();//public abstract省略了
但是现在也可以有普通方法,只是普通前面必须加default
接口是对继承单根性的扩展
接口继承接口不用重写方法
* 但类继承接口必须重写抽象方法
* 接口可以有普通方法,但前面必须加default修饰
因为接口需要子类去实现,所以接口不能implements接口
------------------------------------------------------------------------------------------------
成功的条件只有两种:
1)引用所指向的对象,就是该类型
2)引用所指向的对象,实现了该接口
若不符合如上两个条件,则发生ClassCastException类型转换异常
建议:在强转之前先通过instanceof判断引用指向的对象是否是某种类型
1)自动类型转换:小到大
2)强制类型转换:大到小
------------------------------------------------------------------------------------------------
内部类:
①静态内部类:static修饰
②成员内部类:没有static修饰且定义在外部类类体中
③局部内部类:在方法体或语句块内部定义的类
④匿名内部类
内部类能访问外部类内的一切成员变量和方法,包括私有的
在一个类的声明里声明的类,也叫做内部类或嵌套类,内部类可以作为外部类的一个成员 使用,可以访问外部类的所有成员,包括私有成员。
------------------------------------------------------------------------------------------------
匿名内部类:可以继承一个类或实现一个接口但是不能同时实现一个接口和一个类
由于匿名内部类没有名称,所以类体中不能定义构造方法
由于不知道类名,也不能使用关键字来创建该类的实例
1、若想创建一个类的对象,并且对象只被创建一次
主要用于抽象类、接口的创建;
如abstract class A{abstract void a();}
A a = new A(){void a(){```}}
此时该类不必命名,称之为匿名内部类
注意attention!!!类必须是子类
2、匿名匿名内部类中若想访问外部的变量
该变量必须是final的
问:内部类有自己独立的.class吗
答:有,每个类都有自己一个字节码文件
------------------------------------------------------------------------------------------------
成员内部类:属于实例的
1、成员内部类中的方法可以直接使用外部类的实例变量和实例方法
2、在外部类中可以直接用内部类创建对象
不能定义静态成员
1、类中套类,外面的叫外部类,里面的叫内部类
2、内部类对象通常只在外部类中创建
3、内部类通常只服务于外部类,对外不具备可见性
4、内部类可以直接访问外部类的成员(包括私有的)
内部类有个隐式的引用指向了创建它的外部类对象
外部类.this
在Outer类中定义了一个成员内部类Inner,
在main方法中实例
Outer.In in = new Out().new In()
先实例化外部类,再把内部类当成一个成员变量进行实例化
成员方法中实例化成员内部类可以直接实例化
但是static静态方法中不能直接实例化成员内部类,
需要先实例化外部类对象在new成员内部类对象
但是如果是静态内部类,不管是成员方法还是静态方法都可以直接实例化
再用原来的方法反而会报错
------------------------------------------------------------------------------------------------
静态内部类:
MyOuter.MyInner si=new MyOuter.MyInner();
不在任何方法中,用static修饰
只能访问外部类的静态成员;
不能直接访问外部类的实例变量与实例方法,只有通过对象引用才能访问,不能 用this关键字来访问外部属性
外部类名.静态成员
在另外类中访问:
------------------------------------------------------------------------------------------------
局部内部类
在方法体或语句块(包括方法、构造方法、局部块或静态初始块)内部定义的类称为局部内部类
局部内部类不能加任何访问修饰符也不能用static,但可以使用final和abstract,因为它只对局部块有效
局部变量也是这样
方法中的内部类可以访问外部类成员,对于方法的参数和局部变量,必须有final修饰才可以访问
------------------------------------------------------------------------------------------------
eclipse中的包名中的“.”都是一个文件夹
例“com.tarena.fly”中有三个文件夹
------------------------------------------------------------------------------------------------
变长参数
dosome("1");
dosome("1","1","1","1","1","1");
public static void dosome(String...a){
System.out.println("参数的个数为:"+a.length);}
------------------------------------------------------------------------------------------------
this (代词)
只可用在方法体中,方法中访问成员变量之前默认有个this
用于指代当前对象,哪个对象调就指向哪个对象(调方法)
在构造方法中,一般初始化成员变量的参数和成员变量仅取相同的名号,就用this来区分
------------------------------------------------------------------------------------------------
数组是引用引用数据类型,数组对象存在堆中,数组变量属于引用类型
数组的元素可以看出数组对象的成员变量,只不过类型全相同
------------------------------------------------------------------------------------------------
super()和this()均需放在构造方法的第一行,this和super不能同时出现在一个构造函数里面,this()和super()都指的是对象,均不可以在static环境中使用,从本质上讲,this是一个指向本对象的指针,而super是一个Java关键字,this也是一个关键字
------------------------------------------------------------------------------------------------
子类不能继承父类的构造方法,需要super去调
super关键字可以指代子类的直接父类
但是不可以指代父类的父类
------------------------------------------------------------------------------------------------
子类重写是静态变量被隐藏,静态方法被隐藏
静态方法被重写时,调此方法看的是引用类型
------------------------------------------------------------------------------------------------
包名所有字母都小写
------------------------------------------------------------------------------------------------
注:构造函数与成员变量初始化执行顺序
1)若父类中有静态成员赋值或静态初始化块,执行
2)若类中有静态成员赋值或静态初始化块,执行
3)若都有,先执行父类,在执行子类
若无静态
1)执行父类成员变量
2)父类构造方法
3)子类成员变量 尽管之前子类成员变量还没加载,但已存在只是没有赋值
4)子类构造方法
注:static final声明的数组可以在静态块中初始化
------------------------------------------------------------------------------------------------
构造块再创建对象时被调用,每创建一次就调用一次
静态方法优先执行,父类优先于子类执行
父静,子静,父构块,父构法,子构块,子构法
------------------------------------------------------------------------------------------------
private修饰的方法可以被重载
类中的方法任意方法都可以重载
而静态方法不能被重载
------------------------------------------------------------------------------------------------
方法中参数传递一个字符串引用是
将字符串引用重新指向了一个新的字符串对象,源字符串对象不会发生变化
------------------------------------------------------------------------------------------------
错题:
方法中定义的是局部变量,不能用类成员变量修饰符 private
案例:
public class Something{
void doSomething(){
private String s = "";//此行报错
int l = s.length();
}
}
----------------------------------------------
class Super {
public int getLength() { return 4; } }
public class Sub extends Super {
public long getLength() {
return 5; }
public static void main (String[] args) {
Super sooper = new Super ();
Super sub = new Sub();
System.out.println(sooper.getLength() +"," + sub.getLength()); } }
结果:代码不能被编译
----------------------------------------------
两个类之间没有继承关机不能做强制类型转换
构造方法与类同名,类中可以有和类名相同的方法
static方法中不能处理非static的属性即静态方法中不能引用外部的非静态方法
static方法中不能处理非static的属性即静态方法中不能引用外部的非静态方法