1、内存解析
2、类的成员之一:属性
2.1、变量分类
2.2、成员变量和局部变量的区别
2.3、对象属性的默认初始化值
3、类的成员之二:方法
3.1、重载
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
重载的特点:
与返回值类型无关,只看参数列表,且参数列表必须不同(参数个数或参数类型)
3.2、可变个数的形参
//JDK 5.0
以前:采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a ,String[] books);
//JDK5.0
:采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a ,String…books);
1). 声明格式:方法名(参数的类型名 ...参数名)
2). 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
3).
可变个数形参的方法与同名的方法之间,彼此构成重载
4).
可变参数方法的使用与方法参数使用数组是一致的
functionname(String...args) 和 functionname(String[] args) 一致
5).
方法的参数部分有固定形参,需要放在形参声明的最后
6).
在一个方法的形参位置,最多只能声明一个可变个数形参
3.3、方法参数的值传递机制
形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
4、面向对象的特性之一:封装
4.1、封装概念
将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。
程序设计追求:
高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
低耦合 :仅对外暴露少量的方法用于使用。
4.2、权限修饰符
java语言中
![](https://img-blog.csdnimg.cn/778164412e7c41f4abc740e8ca04ff04.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAd2lzY291cnBlcl8=,size_20,color_FFFFFF,t_70,g_se,x_16)
四种权限修饰符都可以修饰类的内部结构:属性、方法、构造器、内部类
php语言中
只有三种权限修饰符public、protected、private,缺省是默认为public;只能修饰类内部结构,不能修饰类
5、类的成员之三:构造器
5.1、语法格式
修饰符 类名 (参数列表) {
初始化语句;
}
5.2、构造器特征
它具有与类相同的名称
它不声明返回值类型。(与声明为void不同)
不能被
static
、
final
、
synchronized
、
abstract
、
native
修饰,不能有return语句返回值
5.3、构造器作用
创建对象;给对象进行初始化
注意:
一旦显式的定义了构造器,java就不在提供默认构造器了
父类的构造器不可被子类继承
5.4、类属性赋值过程
![](https://img-blog.csdnimg.cn/c3f9675bbd274cc58d692968f67a9b0c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAd2lzY291cnBlcl8=,size_20,color_FFFFFF,t_70,g_se,x_16)
6、this关键字
它在方法内部使用,即这个方法所属对象的引用;
它在构造器内部使用,表示该构造器正在初始化的对象。
this 可以调用类的属性、方法和构造器
当在方法内需要用到调用该方法的对象时,就用
this
。
具体的:我们可以用
this
来区分
属性
和
局部变量
。
比如:
this.name
=
name
;
1.
在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this
,增强程序的阅读性。不过,通常我们都习惯省略this
。
2.
当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this
来表明该变量是类的成员变量
3.
使用
this
访问属性和方法时,如果在本类中未找到,会从父类中查找
7、关键字package\import
7.1、package
package
语句作为
Java
源文件的第一条语句,指明该文件中定义的类所在的包。(
若缺省该语句,则指定为无名包
)
。它的格式为:
package
顶层包名
.
子包名
;
包对应于文件系统的目录,
package
语句中,用
“
.
” 来指明包
(
目录
)
的层次;
包通常用小写单词标识。通常使用所在公司域名的倒置:
com.atguigu.xxx
![](https://img-blog.csdnimg.cn/541f07d5621b45d6b4da5cd232ff4f10.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAd2lzY291cnBlcl8=,size_20,color_FFFFFF,t_70,g_se,x_16)
7.2、import
为使用定义在不同包中的Java类,需用import语句来引入指定包层次下所需要的类或全部类(.*)。import语句告诉编译器到哪里去寻找类。
语法格式:
import
包名
.
类名
;
![](https://img-blog.csdnimg.cn/4e76ea64c58b4569bfb5fe441ac73315.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAd2lzY291cnBlcl8=,size_20,color_FFFFFF,t_70,g_se,x_16)
8、面向对象的特性之二:继承
类继承语法规则:
class Subclass
extends
SuperClass{ }
作用:
继承的出现减少了代码冗余,提高了代码的复用性。
继承的出现,更有利于功能的扩展。
继承的出现让类与类之间产生了关系,提供了多态的前提。
注意:不要仅为了获取其他类中某个功能而去继承
Java
只
支持单继承和多层继承
,不允许多重继承
一个子类只能有一个父类
一个父类可以派生出多个子类
9、方法的重写
方法申明:权限修饰符 返回值类型 方法名(参数类表) throw 异常的类型 {
方法体;
}
定义
:在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的
重置、覆盖
。在程序执行时,子类的方法将覆盖父类的方法。
要求
:
1).
子类重写的方法
必须
和父类被重写的方法具有相同的
方法名称、参数列表
2).
子类重写的方法使用的访问权限
不能小于
父类被重写的方法的访问权限
>子类不能重写父类中声明为
private
权限的方法
3).返回值类型:
>父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
>父类被重写的 方法的返回值类型是A类,则子类重写的方法的返回值类型可以是A类或A类的子类
>父类被重写的方法的返回值类型是基本数据类型,则子类重写的方法的返回值类型必须是相同的基本数据类型
4).
子类方法抛出的异常不能大于父类被重写方法的异常
注意:
声明为
stati的方法不能被重写
10、关键字-super
在
Java
类中使用
super
来调用父类中的指定操作:
>super
可用于访问父类中定义的属性
>super
可用于调用父类中定义的成员方法
>super
可用于在子类构造器中调用父类的构造器
注意:
>尤其当子父类出现同名成员时,可以用
super
表明调用的是父类中的成员
>super
的追溯不仅限于直接父类
>super
和
this
的用法相像,
this
代表本类对象的引用,
super
代表父类的内存空间的标识
>子类中所有的构造器
默认
都会访问父类中
空参数
的构造器
>当父类中没有空参数的构造器时,子类的构造器必须通过
this(
参
数列表
)
或者
super(
参数列表
)
语句指定调用本类或者父类中相应的构造器。同时,只能”
二选一
”
,且必须放在构造器的首行
>如果子类构造器中既未显式调用父类或本类的构造器,且父类中又
没有无参的构造器,则
编译出错
11、面向对象特征之三:多态性
多态性,是面向对象中最重要的概念,在
Java
中的体现:
对象的多态性:父类的引用指向子类的对象 eg:Person p1 = new Man();
>可以直接应用在抽象类和接口上
Java
引用变量有两个类型:
编译时类型
和
运行时类型
。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:
编译
时,看左边;运行时,看右边。
>若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
>多态情况下,“看左边”:
看的是父类的引用(父类中不具备子类特有的方法)
“看右边”:
看的是子类的对象(实际运行的是子类重写父类的方法)
//一个引用类型变量如果声明为父类的类型,但实际引用的是子类
对象,那么该变量就不能再访问子类中添加的属性和方法
Student m = new Student();
m.school = “pku”; //合法,Student类有school成员变量
Person e = new Student();
e.school = “pku”; //非法,Person类没有school成员变量
属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编
译错误。
//多态性应用举例
//方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法
public class Test {
public void method(Person e) {
// ……
e.getInfo();
}
public static void main(Stirng args[]) {
Test t = new Test();
Student m = new Student();
t.method(m); // 子类的对象m传送给父类类型的参数e } }
多态的使用:虚拟方法调用
有了对象的多态性以后,在编译期,只能调用父类中声明过的方法,但在运行期,实际执行的是子类重写父类的方法。
多态的使用前提:
1)类的继承关系;2)要有方法的重写
注意:一旦父类的引用指向子类的对象后,就只能调用继承自父类的成员和子类中重写过父类的方法,无法调用子类特有的成员
重载与重写从编译和运行的角度看:
重载,是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。
它们的调用地址在编译期就绑定了。
Java
的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。
所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为
“早绑定”或“静态绑定”
; 而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体
方法,这称为
“晚绑定”或“动态绑定”
。
多态小结
多态作用:
提高了代码的通用性,常称作接口重用
前提:
>需要存在继承或者实现关系
>有方法的重写
成员方法:
>编译时
:要查看
引用变量所声明的类
中是否有所调用的方法。
>运行时
:调用实际
new
的对象所属的类
中的重写方法。
成员变量:
>不具备多态性,只看引用变量所声明的类。
public class Base {
int count = 10;
public void display() {
System.out.println(this.count);
}
}
public class Sub extends Base {
int count = 20;
public void display() {
System.out.println(this.count);
}
}
public class FieldMethodTest {
public static void main(String[] args){
Sub s = new Sub();
System.out.println(s.count);//20
s.display();//20
Base b = s;
System.out.println(b == s);//true
System.out.println(b.count);//10
b.display();//20
}
}
12、static关键字
12.1、使用范围:
>在Java
类中,可用
static
修饰
属性、方法
、
代码块、内部类
12.2、被修饰后的成员具备以下特点:
>随着类的加载而加载
>优先于对象存在(可以通过“类.静态变量”访问)
>修饰的成员,被所有对象所共享
>访问权限允许时,可不创建对象,直接被类调用
注意:
静态方法中,只能调用静态属性或静态方法,非静态方法中,既可以调用非静态属性和方法,又可以调用静态属性和方法
静态方法内,不能使用this和super关键字
13、类的成员之四:代码块
13.1、代码块的修饰符
代码块如果有修饰的话,只能被static修饰,称为静态代码块;没有使用static修饰的称为非静态代码块;
静态代码块:用
static
修饰的代码块
1).
可以有输出语句。
2).
可以对类的属性、类的声明进行初始化操作。
3).
不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
4).
若有多个静态的代码块,那么按照从上到下的顺序依次执行。
5).
静态代码块的执行要先于非静态代码块。
6).
静态代码块随着类的加载而加载,且只执行一次。
非静态代码块:没有
static
修饰的代码块
1).
可以有输出语句。
2).
可以对类的属性、类的声明进行初始化操作。
3).
除了调用非静态的结构外,还可以调用静态的变量或方法。
4).
若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
5).
每次创建对象的时候,都会执行一次。且先于构造器执行。
14、final关键字
在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。
final
标记的类不能被继承。
提高安全性,提高程序的可读性。
>String类、
System
类、
StringBuffer
类
final
标记的方法不能被子类重写。
>比如:Object
类中的
getClass()
。
final
标记的变量
(
成员变量或局部变量
)
即称为常量。
名称大写,且只能被赋值一次
。
>final修饰属性,可以考虑赋值的位置:显示初始化、代码块中初始化、构造器中初始化
>final修饰局部变量:尤其是final修饰形参时,表明此形参是个常量,一旦进行传参后,只能在此方法体中使用此形参,但不能重新赋值了。
15、抽象类与抽象方法
>
用
abstract
关键字来修饰一个类,这个类叫做
抽象类
。
>
用
abstract
来修饰一个方法,该方法叫做
抽象方法
。
>抽象方法:只有方法的声明,没有方法的实现。以分号结束: 比如:
public abstract void talk()
;
>
含有抽象方法的类必须被声明为抽象类。
>
抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。
不能用
abstract
修饰变量、代码块、构造器;
不能用
abstract
修饰私有方法、静态方法、
final
的方法、
final
的类。
匿名子类:new 抽象类(){重写抽象类的所有抽象方法}
16、接口
接口
(
interface
)
是
抽象方法
和
常量值
定义的集合。
jdk7及以前,只能定义全局常量和抽象方法
>全局常量 public static final,但书写时可以省略这些关键字
>抽象方法 public abstract,但书写时可以省略这些关键字
jdk8 除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
接口的特点:
>用interface
来定义。
>接口中的所有成员变量都
默认
是由
public static final
修饰的。
>接口中的所有抽象方法都
默认
是由
public abstract
修饰的。
>接口中没有构造器。
>接口采用多继承机制。
接口使用
>定义
Java
类的语法格式:
先写
extends
,后写
implements
>class SubClass extends SuperClass
implements
InterfaceA{ }
>一个类可以实现多个接口,接口也可以继承其它接口。
>实现接口的类中必须提供接口中所有方法的具体实现内容,方可实 例化。否则,仍为抽象类。
>接口的主要用途就是被实现类实现。
(面向接口编程)
>与继承关系类似,接口与实现类之间存在多态性
>接口和类是并列关系,或者可以理解为一种特殊的类。从本质上讲,接口是一种特殊的抽象类,这种抽象类中
只包含常量和方法的定义(JDK7.0及之前
)
,而没有变量和方法的实现。
匿名实现类:new 接口(){重写接口中所有的抽象方法}
17、java8中接口的新特性
Java 8
中,你可以为接口添加
静态方法
和
默认方法
。从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。
静态方法:
使用
static
关键字修饰。
可以通过接口直接调用静态方法
,并执行其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中找到像Collection/Collections
或者
Path/Paths
这样成对的接口和类。
默认方法:
默认方法使用
default
关键字修饰。可以通过实现类对象来调用。我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。
比如:
java 8 API
中对
Collection
、
List
、
Comparator
等接口提供了丰富的默认方法。
接口中的静态方法
1)接口定义的静态方法只能通过接口来调用
接口中的默认方法
1)若一个接口中定义了一个默认方法,而另外一个接口中也定义了一个同名同参数的方法(不管此方法是否是默认方法),在实现类同时实现了这两个接 口时,会出现:
接口冲突。
>解决办法:实现类必须覆盖接口中同名同参数的方法,来解决冲突。
2)若一个接口中定义了一个默认方法,而父类中也定义了一个同名同参数的非抽象方法,则不会出现冲突问题。因为此时遵守:
类优先原则。
接口中具有相同名称和参数的默认方法会被忽略。
3)调用接口中默认方法:接口名.super.默认方法名
18、类的成员之五:内部类
1)当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。
2)在
Java
中,允许一个类的定义位于另一个类的内部,前者称为
内部类
,后者称为
外部类
。
3)Inner class
一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
Inner class
的名字不能与包含它的外部类类名相同;
分类:
成员内部类(static成员内部类和非static成员内部类)
成员内部类作为类的成员的角色:
>和外部类不同,Inner class还可以声明为
private
或
protected
;
>可以调用外部类的结构
>Inner class 可以声明为
static
的,但此时就不能再使用外层类的非
static
的成员变量;
成员内部类作为类的角色:
>可以在内部定义属性、方法、构造器等结构
>可以声明为
abstract
类 ,因此可以被其它的内部类继承
>可以声明为
final
的
>编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)
【注意】
1.
非
static
的成员内部类中的成员不能声明为
static
的,只有在外部类或
static
的成员
内部类中才可声明
static
成员。
2.
外部类访问成员内部类的成员,需要
“
内部类
.
成员
”
或
“
内部类对象
.
成员
”
的方式
3. 成员内部类可以直接使用外部类的所有成员,包括私有的数据
4. 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类
声明为静态的
局部内部类(不谈修饰符)
>只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类
>但是它的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类的父类或父接口类型
>内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号,以及数字编号。
>只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类。
>局部内部类可以使用外部类的成员,包括私有的。
>局部内部类可以使用外部方法的局部变量,但是必须是final
的。
由局部内部类和局部变量的声明周期不同所致。
>局部内部类和局部变量地位类似,不能使用public,protected,
缺省
,private
>局部内部类不能使用static
修饰,因此也不能包含静态成员
匿名内部类
>匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new
的后面,用其隐含实现一个接口或实现一个类。
>格式:
new
父类构造器(实参列表)
|
实现接口
(){
//
匿名内部类的类体部分
}
>匿名内部类的特点
匿名内部类必须继承父类或实现接口
匿名内部类只能有一个对象
匿名内部类对象只能使用多态形式引用
内部类总结:
一、成员内部类
1)如何实例化内部类
>静态内部类实例化:
OuterClassName.InnerClassName innerObj = new OuterClassName.InnerClassName();
>非静态内部类实例化:
OuterClassName outerObj = new OuterClassName();
OuterClassName.InnerClassName innerObj = outerObje.new InnerClassName();
2)内部类中调用外部类成员
>调用非静态成员 OuterClassName.this.外部类成员(如果内部类与外部类没有成员名冲突,则可以省略OuterClassName.this.)
->调用静态成员OuterClassName.外部类成员(如果内部类与外部类没有成员名冲突,则可以省略OuterClassName.)
3)外部类中调用内部类成员
>调用非静态成员
内部类对象.成员
>调用静态成员
内部类.成员