目录
包
本质
其实就是文件夹
作用
- 区分同名的类
- 对类进行分类管理
- 按照功能分
- 按照模块分
举例:
- 学生:增加、删除、修改、查询
- 老师:增加、删除、修改、查询
方案1:按功能分:
- 包cn.itcast.add:AddStudent、AddTeacher
- 包cn.itcast.delete:DeleteStudent、DeleteTeacher
- 包cn.itcast.update:UpdateStudent、UpdateTeacher
- 包cn.itcast.find:FindStudent、FindTeacher
方案2:按模块分:
- 包cn.itcast.teacher:
AddTeacher、DeleteTeacher、UpdateTeacher、FindTeacher - 包cn.itcast.student:
AddStudent、DeleteStudent、UpdateStudent、FindStudent
定义
package 包名;
多级分包用 . 分开
注意事项
- package语句必须是程序的第一条可执行代码
- package语句在一个java文件中只能有一个
- 如果没有package,默认表示无包名
常见的编译和运行
- 手动式
A:javac编译当前类文件
B:手动建立包对应的文件夹
C:把a步骤的class文件放到b步骤的最终文件夹下
D:通过java命令执行。注意:需要包名称的执行,如:java cn.itcast.HelloWorld - 自动式
A:javac编译的时候带上 ”-d 当前文件夹“ 即可,如:java -d . HelloWorld.java
B:通过java命令执行,和手动式一样
导包
- 格式:
import 包名…类名;
或者
import 包名…*;(不建议) - package,import,class的顺序:
package > import > class
一个文件中,下列语句包含的数量:
package:只能有一个
import:可以有多个
class:可以有多个,但建议一个
修饰符
分类
- 权限修饰符:private,默认,protected,public
- 状态修饰符:static,final
- 抽象修饰符:abstract
权限修饰符的作用:
本类 | 同一个包下(子类和无关类) | 不同包下(子类) | 不同包下(无关类) | |
---|---|---|---|---|
private | Y | |||
默认 | Y | Y | ||
protected | Y | Y | Y | |
public | Y | Y | Y | Y |
这四种权限修饰符在任意时刻只能出现一种.
说明:Y表示权限修饰符修饰的变量或方法对其他类是可使用的,否则不可直接使用。
常见的类及其组成的修饰
- 类:
可用:默认,public,final,abstract
常用:public - 成员变量:
可用:private,默认,protected,public,static,final
常用:private - 构造方法:
可用:private,默认,protected,public
常用:public - 成员方法:
可用:private,默认,protected,public,static,final,abstract
常用:public
比较常见的修饰组合:
- 成员变量:
public static final - 成员方法:
public static、public abstract、public final
内部类
概述:
把类定义在其他类的内部,这个类被称为内部类
举例:在类A中定义了一个类B,类B就是内部类
访问特点:
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
例子:
class Outer{
private int num = 10;
class Inner{
public void show(){
System.out.println(num);
}
}
public void method(){
//找不到符号
//show();
Inner i = new Inner();
i.show();
}
}
分类:
- 成员内部类:在成员位置定义的类
- 局部内部类:在局部位置定义的类
例子:
class Outer{
private int num = 10;
//成员位置
class Inner{
}
public void method(){
//局部位置
class Inner{
}
}
}
成员内部类
可用修饰符
- private:为了数据的安全性
例:
class Body{
//加private修饰,使得内部类只能被自己的外部类调用
private class Heart{
public void operator(){
System.out.println("心脏搭桥");
}
}
//外部类要提供使用内部类的方法
public void method(){
Heart h = new Heart();
h.operator();
}
}
//调用
Body b = new Body();
b.method();
- static:为了访问的方便性
调用的格式
- 成员内部类不是静态的:
外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
例:
class Outer{
private int num = 10;
class Inner{
public void show(){
System.out.println(num);
}
}
}
class InnerClassDemo{
public static void main(){String[] args){
//格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
- 成员内部类是静态的:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
例:
class Outer{
private int num = 10;
private static int num2 = 100;
//内部类用静态修饰是因为内部类可以看成是外部类的成员
public static class Inner{
public void show(){
//System.out.println(num); 错误:静态内部类访问的外部类数据必须用静态修饰。
System.out.println(num2);
}
public static void show2(){
//System.out.println(num); 错误:静态内部类访问的外部类数据必须用静态修饰。
System.out.println(num2);
}
}
}
class InnerClassDemo{
public static void main(String[] args){
//成员内部类被静态修饰后的访问方式:
//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
oi.show();
oi.show2();
//show2的另一种调用方式
Outer.Inner.show2();
}
}
面试题
要求填空,使分别输出30 ,20 ,10。
class Outer{
public int num = 10;
class Inner{
public int num = 20;
public void show{
int num = 30;
System.out.println(???); //①
System.out.println(???); //②
System.out.println(???); //③
}
}
}
class InnerClassDemo{
public static void main(String[] args){
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
答案:
① num
② this.num
③ new Outer().num 或者 Outer.this.num
注意:
1、内部类和外部类没有继承关系
2、通过外部类名限定this对象:Outer.this
局部内部类
特点
- 可以直接访问外部类的成员
- 在局部位置,刻意创建内部类对象,通过对象调用内部类方法,来使用局部内部类的功能
- 局部内部类访问的局部变量必须加final修饰
(原因:因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存消失,还要使用那个变量,为了让数据能继续被使用,就用final修饰。加final修饰后,变量变成常量)
例子:
class Outer{
private int num = 10;
public void method(){
//错误:从内部类中访问本地变量num2,需要被声明为最终类型
//int num2 = 20;
final int num2 = 20;
class Inner{
public void show(){
System.out.println(num);
System.out.println(num2);
}
}
Inner i = new Inner();
i.show();
}
}
class InnerClassDemo{
public static void main(String[] args){
Outer o = new Outer();
o.method();
}
}
匿名内部类
本质
匿名内部类是内部类的简化写法。
本质是一个继承了父类或者实现了接口的子类匿名对象
前提
存在一个类或者接口
这里的类可以是抽象类或者具体类
格式
new 类名或者接口名(){
重写方法;
};
例子1:(接口只有一个抽象方法的情况)
interface Inter{
public abstract void show();
}
class Outer{
public void method(){
/*
new Inter(){
public void show(){
System.out.println("show");
}
};//无打印任何结果
*/
new Inter(){
public void show(){
System.out.println("show");
}
}.show; //再调用show方法即可打印出信息
}
}
class OuterDemo{
public static void main(String[] args){
Outer o = new Outer();
o.method();
}
}
例子2:(接口有两个或多个抽象方法的情况)
interface Inter{
public abstract void show();
public abstract void show2();
}
class Outer{
public Outer() {
super();
}
public void method() {
Inter inter = new Inter() {
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("show");
}
@Override
public void show2() {
// TODO Auto-generated method stub
System.out.println("show2");
}
};
inter.show();
inter.show2();
}
}
public class InnerClassDemo {
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
}
}
在开发中的使用
在开发过程中,会遇到抽象类或者接口作为参数的方法,此时需要的实际参数是一个子类对象或者实现类对象。
如果该方法仅仅调用一次,则可以使用匿名内部类的格式简化。
例子:(注意比较使用匿名对象和使用匿名内部类的区别)
interface Person{
public abstract void study();
}
class PersonDemo{
public void method(Person person) {
person.study();
}
}
class Student implements Person{
@Override
public void study() {
// TODO Auto-generated method stub
System.out.println("好好学习,天天向上");
}
}
public class InnerClassTest {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
pd.method(new Student());
System.out.println("------------------");
//匿名内部类在开发中的使用
//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(new Person() {
@Override
public void study() {
// TODO Auto-generated method stub
System.out.println("好好学习,天天向上");
}
});
}
}
使用匿名对象,需要先用接口的实现类重写接口方法,然后利用多态实例化接口,可重复多次使用实现类创建对象。
使用匿名内部类,只需直接创建匿名对象并直接重写接口方法即可,只能使用一次。
面试题
按照要求补齐代码,要求在控制台输出“HelloWorld”
interface Inter{
void show();
}
class Outer{
//此处补齐代码
}
class OuterDemo{
public static void main(String[] args){
Outer.method().show();
}
}
答案:
public static Inter method(){
return new Inter(){
@Override
public void show() {
System.out.println("HelloWorld");
}
};
}
分析:
1、Outer.method()可以看出method()应该是Outer中的静态方法
2、Outer.method().show()可以看出method()方法的返回值是一个对象。由于接口Inter中有个show()方法,故认为method()方法的返回值类型是一个接口。