内部类
什么是内部类
将一个类A定义在类B里,里面那个类A就称为内部类,B则称为外部类
内部类的分类
- 成员内部类
- 局部内部类
- 匿名内部类
成员内部类
在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。
成员内部类的格式
class 外部类{
class 内部类{
}
}
成员内部类访问特点
- 内部类可以直接访问外部类的成员,包括私有成员
- 外部类要访问内部类的成员,必须要建立内部类的对象
创建内部类对象格式
外部类名.内部类名 变量名 = new 外部类名().内部类名();
局部内部类
什么是局部内部类
将一个类定义在方法里边,该类就称为局部内部类
如何使用局部内部类
只能在该方法内部使用局部内部类
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
outer.show();
}
}
public class Outer {
public void show(){
// 局部内部类
class Inner{
public void method(){
System.out.println("Inner 局部内部类的method方法执行了....");
}
}
// 在外部类的方法内使用局部内部类
Inner inner = new Inner();
inner.method();
}
}
匿名内部类
使用匿名内部类的前提
匿名内部类必须继承一个父类或者实现一个父接口
匿名内部类的格式
new 父类名或者接口名(){
// 方法重写
@Override
public void method() { // 执行语句
}
};
匿名内部类的使用
以接口为例,匿名内部类的使用,代码如下
-
定义接口
public interface FlyAble{ public abstract void fly(); }
-
方式一 创建匿名内部类,并调用
public class InnerDemo { public static void main(String[] args) { //直接new接口,无需写实现类来实现接口 new FlyAble(){ //直接实现方法 public void fly() { System.out.println("我飞了~~~"); } }.fly(); } }
-
方式二 常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。
public class InnerDemo2 { public static void main(String[] args) { FlyAble f = new FlyAble(){ //直接重写抽象方法 public void fly(){ System.out.println("我要飞,飞啊,飞,,"); } @Override public void fly2() { System.out.println("我要飞,飞啊,飞,,2222"); } }; f.fly(); f.fly2(); } }
-
方式三 匿名内部类调用
public class InnerDemo3 { public static void main(String[] args) { showFly(new FlyAble() { @Override public void fly() { System.out.println("9999999"); } @Override public void fly2() { System.out.println("888888888"); } }); } public static void showFly(FlyAble f){ f.fly(); f.fly2(); } }
匿名内部类好处:可以不用再写一个实现类来实现接口,可以直接使用
引用类型方法的参数和返回值
普通类-作为方法的参数及返回值
-
代码演示:普通类-作为方法的形参
普通类-作为方法的形参 方法的形参是类名,其实需要的是该类的对象 实际传递的是该对象的【地址值】
public class Student { public void study(){ System.out.println("好好学习,天天向上"); } } public class StudentDemo { //把普通类当作一个参数 public void method(Student student){ student.study(); } } public class StudentTest { public static void main(String[] args) { StudentDemo st = new StudentDemo(); Student s = new Student(); st.method(s); } }
-
代码演示:普通类-作为方法的返回值类型
普能类-作为方法的返回值 方法的返回值是类名,其实返回的是该类的对象 实际传递的,也是该对象的【地址值】
public class Student { public void study(){ System.out.println("好好学习,天天向上"); } } public class StudentDemo { //返回值类型为一个类 public Student getStudent(){ return new Student(); } } public class StudentTest { public static void main(String[] args) { StudentDemo st = new StudentDemo(); //返回也是一个对象 Student student = st.getStudent(); student.study(); } }
抽象类-作为方法的参数及返回值
-
抽象类作为形参和返回值
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
-
代码演示:作为形参
public abstract class Person { public abstract void study(); } public class PersonDemo { public void method(Person p){ p.study(); } } //抽象类作为参数,必须实例化 public class Student extends Person { @Override public void study() { System.out.println("好好学习,天天向上!!"); } } //测试 public class PersonTest { public static void main(String[] args) { PersonDemo pd = new PersonDemo(); //抽象类需要一个具体类来实现 Person p = new Student(); //method的参数是一个抽象类,那抽象类如何实例化呢? 多态的方式 pd.method(p); } }
-
代码演示:作为返回值
public abstract class Person { public abstract void study(); } public class PersonDemo { //返回对象是一个抽象类 public Person getPerson(){ //person是一个抽象类,只能通过多态的方法实例化 // Person p = new Student(); // return p; return new Student(); } } //具体子类实现抽象类Person public class Student extends Person { @Override public void study() { System.out.println("好好学习,天天向上!!"); } } //测试 public class PersonTest { public static void main(String[] args) { PersonDemo pd = new PersonDemo(); Person person = pd.getPerson(); person.study(); } }
接口类-作为方法的参数及返回值
-
接口作为形参和返回值
- 方法的形参是接口名,其实需要的是该接口的实现类对象
- 方法的返回值是接口名,其实返回的是该接口的实现类对
-
代码演示: 接口作为形参
public interface Love { public abstract void show(); } public class LoveDemo { //接口作为参数 public void method(Love love){ love.show(); } } //子类实现接口 public class LoveImpl implements Love { @Override public void show() { System.out.println("爱一燕"); } } //测试 public class LoveTest { public static void main(String[] args) { LoveDemo ld = new LoveDemo(); //需要对接口的参数进行实现化,多态的方法 Love love = new LoveImpl(); //参数需要的是一个接口 ld.method(love); } }
-
代码演示: 接口作为返回值
public interface Love { public abstract void show(); } public class LoveDemo { //接口作为返回值 public Love getLove(){ // 接口不能直接返回,需要实例化,多态的方式 // Love love = new LoveImpl(); // return love; return new LoveImpl(); } } //子类实现接口 public class LoveImpl implements Love { @Override public void show() { System.out.println("爱一燕"); } } //测试 public class LoveTest { public static void main(String[] args) { LoveDemo ld = new LoveDemo(); Love love = ld.getLove(); love.show(); } }
final关键字
final概述
学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们能不能随意的继承API中提供的类,改写其内容呢?显然这是不合适的。为了避免这种随意改写的情况,Java提供了final关键字,用于修饰不可改变内容。
final特点
不可变,可以用于修饰类、方法和变量
- 类:被修饰的类,不能被继承
- 方法:被修饰的方法,不能被重写
- 变量:被修饰的变量,不能被重新赋值,变成了常量
final使用
修饰类
//final修饰类
public final class Fu {
public void show(){
System.out.println("fu..show..");
}
}
//子类不能继承final所修饰的父类
public class Zi extends Fu {
}
修饰方法
public class Fu {
public final void show(){
System.out.println("fu..show..");
}
}
public class Zi extends Fu {
//子类继承父类中的final修饰的方法
public void show(){
System.out.println("fu..show..");
}
}
修饰变量
public class Fu {
final int num = 10;
public void show(){
System.out.println("fu..show..");
}
}
public class Test {
public static void main(String[] args) {
Fu f = new Fu();
System.out.println(f.num);//10
// f.num = 20; final修饰的变量,变成常量,不能进行修改
}
}
包的定义及规范
分包思想
如果将所有的类文件都放在一个包下,不利于管理和后期维护
所以,对于不同动能的类文件,可以放在不同的包下进行管理
什么是包
包:本质上就是文件夹
- 创建包:单级包、多级包
- 多级包之间使用:使用“.”进行分割
- 多级包的定义规范:公司的网站地址反转(去掉www)
- 包的命名规则:字母都是小写
包的定义
- 使用
package
关键字定义包 - 格式
package 包名; 如果是多级包,中间用“.”进行分割
- 注意:一般情况下,我们不会手动的去给某一个类定义包,使用idea开发工具创建即可
包的注意事项
- package语句必须是程序的第一句可执行的代码
- package语句在一个Java文件中只能有一个
- 如果没有package,默认表示为无包名
类与类之间的访问
- 同一个包下的访问:不需要导包,直接使用即可
- 不同包下的访问:import导包后访问
- 通过全类名(包名+类名)访问
注意:import、package、class三个关键字的摆放位置存在顺序关系 - package:必须是程序的第一条可执行代码
- import:需要写在package下面
- class:需要写在import下面
权限修饰符
权限概述
在Java中提供了四种不同的访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限
- public:公共的
- protected:受保护的
- default:默认的
- private:私有的
不同权限的访问范围
public | protected | default(空的) | private | |
---|---|---|---|---|
同一个类 | √ | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包的无关类 | √ |
总结
- 在四大权限中,public是最大的权限,private是最小的权限
- 在编写代码时,如果没有特殊的考虑,建议以下使用方式;
- 成员变量使用 private ,隐藏细节。
- 构造方法使用 public ,方便创建对象。
- 成员方法使用 public ,方便调用方法
static关键字
什么是static关键字
它可以用来修饰成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用了。
static的定义和使用格式
static的特点:(它可以修饰成员变量,还可以修饰成员方法)
A:随着类的加载而加载
回想main方法。
B:优先于对象存在
C:被类的所有对象共享
举例:咱们班级的学生应该共用同一个班级编号。
其实这个特点也是在告诉我们什么时候使用静态?
如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
举例:
饮水机(用静态修饰)
水杯(不能用静态修饰)
D:可以通过类名调用
其实它本身也可以通过对象名调用。
推荐使用类名调用。
静态修饰的内容一般我们称其为:与类相关的,类成员
静态代码块
什么是静态代码块
定义在成员位置,使用static修饰的代码块{}
- 位置:类中方法外
- 执行:随着类的加载而执行且执行一次,优先于main方法和构造方法的执行
静态代码块格式
public class ClassName{
static {
// 执行语句
}
}