包
1.包的概述
1.为什么要有包?
-
将字节码(.class)进行分类存放
-
包其实就是文件夹
2.包的概述
举例:
学生:增加,删除,修改,查找
老师:增加,删除,修改,查找
方案一:按功能分
com.heima.add
AddStudent
AddTeacher
com.heima.delete
DeleteStudent
DeleteTeacher
com.heima.update
UpdateStudent
UpdateTeacher
com.heima.find
FindStudent
FindTeacher
方案二:按模块分
com.heima.teacher
AddTeacher
DeleteTeacher
UpdateTeacher
FindTeacher
com.heima.student
AddStudent
DeleteStudent
UpdateStudent
FindStudent
3.包的命名
域名:www.heima.com
反向域名:com.heima
二.定义包
1.定义包的格式
- package 包名
- 多级包用.分开即可
2定义包的注意事项
- package语句必须是程序的第一条可执行语句
- package语句在一个java文件中只能有一个
- 如果没有package,默认表示无包名
3.导包(import)
1.为什么要有import
- 其实就是让有包的类对调用者可见,不用写全类名了
2.导包格式
- import 包名;
注意
这种方式导入的是类的名称,虽然可以最后写*,但是不建议
import java.util.*; //*代表通配符,他会到该包下挨个匹配,匹配上就会导入
案例演示
import package1.person;
import package3.student;
import java.util.Scanner; //在开发中我们用的都是导入具体的类
import java.util.*; //*代表通配符,他会到该包下挨个匹配,匹配上就会导入
public class Demo_package2_person {
public static void main(String[] args) {
//package1.person p = new package1.person("张三",23);没导包要写全类名
person p = new person("张三",23);//导包不用写
System.out.println(p.getName() + "..." + p.getAge());
//p.print(); //在不同包下的无关类,不允许访问,因为是protected修饰的
//复习一下
/*Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
System.out.print(x);*/
student s = new student("李四",24);
System.out.println(s.getName() + "..." + s.getAge());
s.method();
}
}
四种权限修饰符的引用
本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
- private Y N N N
默认(不加任何修饰符) Y Y N N
protected Y Y Y N
public Y Y Y Y
类及其组成的常见修饰符
A:修饰符:
- 权限修饰符:private,默认的,protected,public
- 状态修饰符:static,final
- 抽象修饰符:abstract
B:类
- 权限修饰符:默认修饰符,public
- 状态修饰符:final
- 抽像修饰符:abstract
- 用的最多的就是:public
C:成员变量
-
权限修饰符:private,默认的,protected,public
-
状态修饰符:static,final
-
用的最多的就是:private
D:构造方法
-
权限修饰符:private,默认的,protected,public
-
用的最多的就是:public
E:成员方法
-
权限修饰符:private,默认的,protected,public
-
状态修饰符:static,final
-
抽象修饰符:abstract
-
用的最多的就是:public
F:除此以外的组合规则
成员变量:public static final
成员方法:
- public static
- public abstract
- public final
内部类
1.概述:
- 在类中定义类
2.内部类访问特点
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
- 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
案例演示
public class Demo_package3_Innerclass {
public static void main(String[] args) {
//Inner i = new Inner();
//i.method();
//外部类名.内部类名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();//创建内部类对象
oi.method();
}
}
class Outer {
private int num = 10;
class Inner {
public void method() {
System.out.print(num);
}
}
}
3.内部类私有的使用
- 通过外部类创建对象,在主类创建外部类对象调用
案例演示
public class Demo_package3_Innerclass1 {
public static void main(String[] args) {
//Outer1.Inner1 oi = new Outer1().new Inner1();Inner1被私有不能访问
//oi.method();
Outer1 o = new Outer1();
o.print();
}
}
class Outer1 {
private int num = 10;
private class Inner1 { //内部类被私有
public void method() {
System.out.print(num);
}
}
public void print() {
Inner1 i = new Inner1();
i.method();
}
}
4.静态的内部类使用
静态内部类非静态方法的调用
- 外部类名.内部类名 对象名 = 外部类名.内部类对象;
静态内部类静态方法的调用
- 外部类名.内部类名.方法名;
案例演示
public class Demo_package3_Innerclass2 {
public static void main(String[] args) {
//外部类名.内部类名 对象名 = 外部类名.内部类对象
Outer2.Inner oi = new Outer2.Inner();
oi.method();
Outer2.Inner2.print();
}
}
class Outer2 {
static class Inner {
public void method() {
System.out.println("method");
}
}
static class Inner2 {
public static void print() {
System.out.println("print");
}
}
}
5.内部类与外部类成员变量的调用
- 内部类之所以能获取到外部类的成员,是因为他能获取到外部类的引用:外部类名.this.变量名
- 内部类调用自己的成员变量用this.变量名
- 方法中的变量根据就近原则,直接用变量名
案例演示
public class Demo_package3_Innerclass3 {
public static void main(String[] args) {
Outer3.Inner oi = new Outer3().new Inner();
oi.show();
}
}
//依次输出30,20,10
class Outer3 {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(Outer3.this.num);
}
}
}
6.局部内部类访问局部变量
- 局部内部类只能在其所在的方法访问
- 局部内部类访问局部变量必须用final修饰
为什么?
因为当调用这方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失却想用这个局部变量时就没有了,如果final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的变量还在,也可以继续使用但是jdk1.8取消了这个事情,所以我认为这是个bug
案例演示
public class Demo_package3_Innerclass4 {
public static void main(String[] args) {
Outer4 o = new Outer4();
o.method();
}
}
class Outer4 {
public void method() {
final int num = 10;
class Inner {
public void print() {
System.out.print(num);
}
}
Inner i = new Inner();
i.print();
}
/*public void run() { //局部内部类,只能在其所在的方法中访问
Inner i = new Inner();
i.print();
}*/
}
7.匿名内部类
就是内部类的简化写法
前提:存在一个类或者接口
- 这里的类可以是具体类也可以是抽象类
格式:
new 类名或者接口名() {
重写方法;
};
本质是什么?
- 是一个继承了该类或者实现了该接口的子类匿名对象
案例演示
public class Demo_package3_Innerclass5 {
public static void main(String[] args) {
Outer5 o = new Outer5();
o.method();
}
}
interface Inter {//接口
public void print();
}
class Outer5 {
/*class Inner implements Inter {//有名内部类
public void print() {
System.out.println("print");
}
}*/
public void method() {
//Inner i = new Inner();
//i.print();
//new Inner().print();调用有名内部类中的方法
new Inter() { //实现Inter接口
public void print() { //重写抽象方法
System.out.println("print");
}
}.print();
}
}
8.匿名内部类重写多个方法调用
第一种方法:
public class Demo_package3_Innerclass6 {
public static void main(String[] args) {
Outer6 o = new Outer6();
o.method();
}
}
interface Inter1 {
public void show1();
public void show2();
}
class Outer6 {
public void method() {
//匿名内部类只针对重写一个方法时使用
new Inter1() {
public void show1() {
System.out.println("print1");
}
public void show2() {
System.out.println("print2");
}
}.show1();
new Inter1() {
public void show1() {
System.out.println("print1");
}
public void show2() {
System.out.println("print2");
}
}.show2();
}
}
第二种方法:
public class Demo_package3_Innerclass6 {
public static void main(String[] args) {
Outer6 o = new Outer6();
o.method();
}
}
interface Inter1 {
public void show1();
public void show2();
}
class Outer6 {
public void method() {
//匿名内部类只针对重写一个方法时使用
Inter1 i = new Inter1() {
public void show1() {
System.out.println("print1");
}
public void show2() {
System.out.println("print2");
}
/*public void show3() {
System.out.println("print3");
}*/
};
i.show1();
i.show2();
//i.show3(); //匿名内部类是不能向下转型的,因为没有子类类名
}
}
9.匿名内部类在开发中的应用
- 匿名内部类当作参数传递(本质把匿名内部类看作一个对象)
案例分析
public class Demo_package3_Innerclass7 {
public static void main(String[] args) {
PersonDemo pd = new PersonDemo();
//pd.method(new Student());
pd.method(new Person() { //匿名内部类当作参数传递(本质把匿名内部类看作一个对象)
public void show() {
System.out.print("show");
}
});
}
}
//这里写抽象类和接口都行
abstract class Person {
public abstract void show();
}
class PersonDemo {
public void method(Person p) {
p.show();
}
/*public void method(Person p) { //Person p = new Student();
p.show();
}*/
/*
Person p = new Person(){ //父类引用指向子类对象
public void show() {
System.out.print("show");
}
}*/
}
/*class Student extends Person {
public void show() {
System.out.print("show");
}
}*/