java基础
内部类
基本介绍:
一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类,嵌套其他类的类称为外部类。是我们类的第五大成员[属性,方法,构造器,代码块,内部类],内部类最大特点是可以直接访问私有属性,可以体现类与类之间的包含关系。
基本语法:
class Outer{//外部类
class Inner{//内部类
}
}
class Other{//外部其他类
}
例子
package org.example.controler;
public class InnerClass01 {//外部其他类
public static void main(String[] args) {
}
}
class Outer{//外部类
private int n1 = 100;//属性
public Outer(int n1) {//构造器
this.n1 = n1;
}
public void m1(){
System.out.println("m1()");
}
{//代码块
System.out.println("代码块");
}
class Inner{//内部类
}
}
局部内部类的使用
说明:
局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。
- 可以直接访问外部类的所有成员,包含私有的
- 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
- 作用域:仅仅在定义它的方法或代码块中。
- 局部内部类–访问---->外部类的成员[访问方式:直接访问]
- 外部类–访问—>局部内部类的成员
- 外部其他类–不能访问---->局部内部类(因为 局部内部类地位是一个局部变量)
- 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
package org.example.controler;
public class LocalInnerClass {
public static void main(String[] args) {
//演示
Outer02 outer02 = new Outer02();
outer02.m1();
}
}
class Outer02{//外部类
private int n1 = 100;
private void m2(){
System.out.println("Ourter02 m2()");
}//私有方法
public void m1(){//方法
//1.局部内部类是定义在外部类的局部位置,通常在方法
//3.不能添加访问修饰符,但是可以使用final修饰,加上final就不可以继承这个类了,否则可以继承
//4.作用域:仅仅在定义它的方法或代码块中
final class Inner02{//局部内部类(本质仍然是一个类)
//2.可以直接访问外部类的所有成员,包含私有的
private int n1=800;
public void f1(){
//5.局部内部类可以直接访问外部类的成员,比如下面 外部类n1和m2()
//7.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
//Outer02.this本质就是外部类的对象,即哪个对象调用了m1,Outer02.this就是哪个对象
System.out.println("n1="+n1+"外部类的n1="+Outer02.this.n1);
m2();
}
}
//6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
Inner02 inner02= new Inner02();
inner02.f1();
}
}
记住:1.局部内部类定义再方法中/代码块
2.作用域在方法体或者代码块中
3.本质仍然是一个类
匿名内部类的使用
大致概括:
- 本质是类
- 内部类
- 该类没有名字
- 同时还是一个对象
说明:
匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
基本语法:
new 类或接口(参数列表){
类体
};
案例:
package org.example.controler;
/**
* 演示匿名内部类的使用
*/
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
class Outer04{//外部类
private int n1 = 10;//属性
public void method(){//方法
//基于接口的匿名内部类
//1.需求:想使用A接口,并创建对象
//2.传统方式,是写一个类,实现该接口
//3.老韩需求是 Tiger 类只是使用一次,后面再不使用
//4.可以使用匿名内部类来简化开发
//5.tiger1的编译类型是 A
//6.tiger1的运行类型是 就是匿名内部类 XXX=> Outer04$1
/*
我们看底层 会分配 类名 Outer04$1
class XXX implements A{
@Override
public void cry() {
System.out.println("老虎叫换、、、、、");
}
}
* */
//7.jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了Outer04$1实例,并且把地址
//返回给tiger1
//8.匿名内部类使用一次就不能再使用了
A tiger1 = new A(){
@Override
public void cry() {
System.out.println("老虎叫换、、、、、");
}
};
System.out.println("tiger1的运行类型:"+tiger1.getClass());
tiger1.cry();
A tiger = new Tiger();
tiger.cry();
}
}
interface A{//接口
public void cry();
}
class Tiger implements A{
@Override
public void cry() {
System.out.println("老虎叫唤....");
}
}
class Dog implements A{
@Override
public void cry() {
System.out.println("小狗汪汪叫");
}
}
class Father{//类
public Father(String name){//构造器
super();
}
public void test(){//方法
}
}
基于类的匿名内部类:
案列:
package org.example.controler;
/**
* 演示匿名内部类的使用
*/
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
class Outer04{//外部类
private int n1 = 10;//属性
public void method(){//方法
//基于接口的匿名内部类
//1.需求:想使用A接口,并创建对象
//2.传统方式,是写一个类,实现该接口
//3.老韩需求是 Tiger 类只是使用一次,后面再不使用
//4.可以使用匿名内部类来简化开发
//5.tiger1的编译类型是 A
//6.tiger1的运行类型是 就是匿名内部类 XXX=> Outer04$1
/*
我们看底层 会分配 类名 Outer04$1
class XXX implements A{
@Override
public void cry() {
System.out.println("老虎叫换、、、、、");
}
}
* */
//7.jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了Outer04$1实例,并且把地址
//返回给tiger1
//8.匿名内部类使用一次就不能再使用了
A tiger1 = new A(){
@Override
public void cry() {
System.out.println("老虎叫换、、、、、");
}
};
System.out.println("tiger1的运行类型:"+tiger1.getClass());
tiger1.cry();
// A tiger = new Tiger();
// tiger.cry();
//演示基于类的匿名内部类
//1.father编译类型 Father
//2.father运行类型 Outer04$2
//3.底层会创建匿名内部类
/*
* class Outer04$2 extends Father{
*
* }
* */
//4.同时也直接返回了 匿名内部类 Outer04$2的对象
//5.注意("jack")参数列表会传递给构造器
Father father = new Father("jack"){
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
};
father.test();
System.out.println("father的运行类型"+father.getClass());
//基于抽象类的匿名内部类
Animal animal = new Animal(){
@Override
void eat() {
System.out.println("小狗吃骨头");
}
};
animal.eat();
}
}
interface A{//接口
public void cry();
}
class Tiger implements A{
@Override
public void cry() {
System.out.println("老虎叫唤....");
}
}
class Dog implements A{
@Override
public void cry() {
System.out.println("小狗汪汪叫");
}
}
class Father{//类
public Father(String name){//构造器
System.out.println("name的值为"+name);
}
public void test(){//方法
}
}
abstract class Animal{//抽象类
abstract void eat();
}
使用方法:
案列:
package org.example.controler;
public class AnonymousInnerClassDetail {
public static void main(String[] args) {
Outer05 outer05 = new Outer05();
outer05.f1();
}
}
class Outer05{
private int n1 = 99;
public void f1(){
//创建一个基于类的匿名内部类
Person p = new Person(){
@Override
public void hi() {
System.out.println("匿名内部类重写了hi方法");
}
};
p.hi();//动态绑定,运行类型是Outter05$1
//也可以直接调用,匿名内部类本身也是返回了一个对象的
new Person(){
@Override
public void hi() {
System.out.println("匿名内部类重写了hi方法,哈哈哈、、、");
}
@Override
public void ok(String str) {
super.ok(str);
}
}.ok("jack");
}
}
class Person{
public void hi(){
System.out.println("Person 里面的hi()");
}
public void ok(String str){
System.out.println("Person 里面的ok()传的值为:"+str);
}
}
匿名内部类的最佳实践
当做实参直接传递,简洁高效
案例1
package org.example.controler;
public class InnerClassExercise01 {
public static void main(String[] args) {
//当作实参直接传递,简洁高效
f1(new IL() {
@Override
public void show() {
System.out.println("这是一幅名画");
}
});
//传统方法
f1(new Picture());
}
//静态方法,形参是接口类型
public static void f1(IL il){
il.show();
}
}
//接口
interface IL{
public void show();
}
//类->实现IL=>硬编码
class Picture implements IL{
@Override
public void show() {
System.out.println("这是一幅名画。。。。。");
}
}
案例2
package org.example.controler;
public class InnerClassExercise02 {
public static void main(String[] args) {
/*
* 1.有一个铃声接口Bell,里面有个ring 方法。
* 2.有一个手机类Cellphone,具有闹钟功能alarmclock,参数是Bell类型
* 3.测试手机类的闹钟功能,通过匿名内部类(对象)作为参数,打印:拦住起床了
* 4.再传入另一个匿名内部类(对象),打印:小伙伴上课了
* */
Cellphone cellphone = new Cellphone();
cellphone.alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床了");
}
});
cellphone.alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("小伙伴们上课了");
}
});
}
}
interface Bell{
void ring();
}
class Cellphone{
public void alarmClock(Bell bell){
bell.ring();
}
}
成员内部类:
说明:
成员内部类是定义在外部类的成员位置,并且没有static修饰。
1.可以访问外部类的所有成员,包含私有的
2.可以添加任意访问修饰符(public,protected,默认,private)因为它的地位就是一个成员
案例:
package org.example.controler;
public class MemberInnerClass01 {
public static void main(String[] args) {
Outer08 outer08 = new Outer08();
outer08.t1();
}
}
class Outer08{//外部类
private int n1 = 10;
public String name= "张三";
//注意:成员内部类,是定义在外部类的成员位置上
class Innter08{//成员内部类
public void say(){
//可以直接访问外部类的所有成员,包含私有的
System.out.println("Outer08的n1="+n1+"Outer08的name="+name);
}
}
//写方法
public void t1(){
//使用了成员内部类
Innter08 innter08 = new Innter08();
innter08.say();
}
}
3.作用域和外部类的其它成员一样,为整个类体比如前面案列,在外部类的成员内部类对象,再调用方法
4.成员内部类–访问—>外部类(比如:属性)[访问方式:直接访问]
5.外部类–>访问------>内部类访问方式:创建对象,再访问
6.外部其他类—访问—>成员内部类
静态内部类:
说明:
静态内部类是定义在外部的成员位置,并且有static修饰
1.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
2.可以添加任意访问修饰符,因为它的地位就是一个成员
3.作用域:同其它的成员,为整个类体
4.静态内部类–访问---->外部类(比如:静态属性)[访问方式:直接访问所有静态成员]
5.外部类—访问----->静态内部类 访问方式:创建对象,再访问
6.外部其它类–访问----->静态内部类
7.如果外部类和静态内部类的成员重名时,静态内部类访问时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问
枚举
什么是枚举
1.枚举是一组常量的集合。
2.枚举属于一种特殊的类,里面只包含有限的特定的对象
实现枚举的方式
自定义枚举:
说明:
1.不需要提供setXxx方法,因为枚举对象值通常为只读。
2.对枚举对象/属性使用final+static共同修饰,实现底层优化。
3.枚举对象名通常使用全部大写,常量的命名规范。
4.枚举对象根据需要,也可以有多个属性。
案例:
package org.example.enums;
public class Enumeration02 {
public static void main(String[] args) {
System.out.println(Season.SPRING.getName()+" "+Season.SPRING.getDesc());
}
}
class Season{//类
private String name;
private String desc;
//定义了四个对象
public static final Season SPRING = new Season("春天", "温暖");
public static final Season SUMMER = new Season("夏天", "炎热");
public static final Season WINTER = new Season("冬天", "寒冷");
public static final Season AUTUMN = new Season("秋天", "凉爽");
//1.将构造器私有化,目的 防止直接new
//2.去掉set方法,防止属性被修改
//3.在Season内部,直接创建固定的对象
//4.优化,可以加入 final 修饰
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
}
enum关键字实现枚举
案例
package org.example.enums;
public class Enumeration03 {
public static void main(String[] args) {
System.out.println(Season.SPRING);
}
}
enum Season{//类
// //定义了四个对象
// public static final Season SPRING = new Season("春天", "温暖");
// public static final Season SUMMER = new Season("夏天", "炎热");
// public static final Season WINTER = new Season("冬天", "寒冷");
// public static final Season AUTUMN = new Season("秋天", "凉爽");
//1.使用关键字enum来实现枚举类
//2.使用SPRING("春天","温暖") 解读 常量名(实参列表)
//3.如果有多个常量(对象),使用 , 号间隔即可
//4.如果使用enum来实现枚举,要求将定义常量对象,写在前面
//5.如果使用的时无参构造器,可以省略小括号如WATH
SPRING("春天","温暖"),
WINTER("冬天", "寒冷"),
WATH;
private String name;
private String desc;
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
private Season(){
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
注意事项:
1.当我们使用enum关键字开发一个枚举类时,默认会继承Enum类
2.传统的public static final Season SPRING = new Season(“春天”,“温暖”);简化成SPRING(“春天”,“温暖”),这里必须知道,它调用是哪个构造器。
3.如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略
4.当有多个枚举对象时,使用,间隔,最后有一个分号结尾
5.枚举对象必须放在枚举类的行首
enum常用方法应用实列
1.toString:Enum类已经重写过了,返回的是当前对象名,子类可以重写该方法,用于返回对象的属性信息
2.name:返回当前对象名(常量名),子类中不能重写
3.ordinal:返回当前对象的位置号,默认从0开始
4.values:返回当前枚举类中所有的常量
5.valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常
6.compareTo:比较两个枚举常量,比较的就是编号
案列
package org.example.enums;
public class EnumMethod {
public static void main(String[] args) {
Season autumn = Season.AUTUMN;
//输入枚举对象的名字
System.out.println(autumn.name());
//ordinal()输出的是该枚举对象的次序/编号,从0开始编号
System.out.println(autumn.ordinal());
//values返回的是Season的数组,含有所有的枚举对象
Season[] values = Season.values();
for (Season season:values) {
System.out.println(season);
}
//valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常
//执行流程
//1.根据你输入的"AUTUMN"到Season的枚举对象去查找
//2.如果找到了,就返回,如果没有找到,就报错
Season season = Season.valueOf("AUTUMN");
System.out.println(season);
//compareTo:比较两个枚举常量,比较的就是编号
//输出结果为Season.SPPRING-Season.WINTER
System.out.println(Season.SPRING.compareTo(Season.WINTER));
}
}
enum实现接口
1.使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而Java是单继承机制。
2.枚举类和普通类一样,可以实现接口,如下形式。
enum 类名 implements 接口1,接口2{}
注解
理解
1.注解也被称为元数据,用于修饰解释 包,类,方法,属性,构造器,局部变量等数据信息
2.和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入再代码中的补充信息
3.在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替java EE旧版中所遗留的繁冗代码和XML配置等
三个基本注解
1.@Override:限定某个方法,是重写父类方法,该注解只能用于方法
2.@Deprecated:用于表示某个程序元素(类,方法等)已过时
到Season的枚举对象去查找
//2.如果找到了,就返回,如果没有找到,就报错
Season season = Season.valueOf(“AUTUMN”);
System.out.println(season);
//compareTo:比较两个枚举常量,比较的就是编号
//输出结果为Season.SPPRING-Season.WINTER
System.out.println(Season.SPRING.compareTo(Season.WINTER));
}
}
##### enum实现接口
1.使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而Java是单继承机制。
2.枚举类和普通类一样,可以实现接口,如下形式。
enum 类名 implements 接口1,接口2{}
## 注解
### 理解
1.注解也被称为元数据,用于修饰解释 包,类,方法,属性,构造器,局部变量等数据信息
2.和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入再代码中的补充信息
3.在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替java EE旧版中所遗留的繁冗代码和XML配置等
### 三个基本注解
1.@Override:限定某个方法,是重写父类方法,该注解只能用于方法
2.@Deprecated:用于表示某个程序元素(类,方法等)已过时
3.@SupperssWarnings:抑制编译器警告