内部类
成员内部类
-
能够共享外部类的所有[静态+非静态]成员[属性+方法]
-
如何理解其与外部类的关系:蛔虫和牛的关系
-
如何创建其对象:
Outer.Inner in = new Outer().new Inner(); //或者 Outer out = new Outer(); Outer.Inner in = out.new Inner();
-
例如:
class Outer{ int a = 3; //成员变量 static int b = 5; //静态变量 class Inner{ //成员内部类 int x = 7; public void test(){ System.out.println(a);//true System.out.println(b);//true System.out.println(x);//true } } }
静态内部类
-
只能共享外部类的静态成员[属性+方法]
Q:java中,在同一个类中,为什么静态方法无法访问到非静态的变量? A:在Java中,在同一个类中,静态方法无法直接访问非静态变量的原因是存在对应的生命周期差异。 静态方法是属于类本身的方法,它在类加载的时候就已经存在,可以直接通过类名调用。而非静态变量是属于类的实例的,需要在创建对象之后才能使用。 因为静态方法不依赖于类的实例,它不会自动获取任何实例级别的信息。相比之下,非静态变量是与类的实例关联的,只有在创建对象后才会分配内存空间。 由于静态方法在没有实例化对象的情况下就可以调用,而非静态变量必须依附于实例存在,所以静态方法无法直接访问非静态变量。如果需要在静态方法中访问非静态变量,必须通过创建对象的方式来访问。
-
如何理解其与外部类的关系:房客和房东的关系
-
如何创建其对象
Outer.Inner in = new Outer.Inner();
-
例如
class Outer{//房东 int a = 3; static int b = 5; static class Inner{//房客 int x = 7; static int y = 9; public void test(){ System.out.println(a);//false System.out.println(b);//true System.out.println(x);//true (取决于test是否是非静态的),如果test为static,则无法访问到x System.out.println(y);//true } } }
-
作用
静态内部类的主要用途包括: 1. 代码组织和封装:静态内部类可以将相关的代码组织在一起,提高代码的可读性和维护性。它能够将实现细节封装在内部类中,并与外部类进行隔离,使代码更加清晰和模块化。 2. 辅助功能的实现:静态内部类常用于实现辅助功能或特定功能的类,比如迭代器、比较器等。这些类可以被外部类或其他类使用,有助于实现特定的操作或提供特定的功能。 3. 提供私有的实现细节:静态内部类可以使一些实现细节对外部不可见,只在内部类内部可访问。这有助于隐藏实现细节,增加代码的安全性和可维护性。 4. 实现多重继承效果:Java中不支持多继承,但静态内部类可以作为外部类的成员独立存在,并且静态内部类可以实现多个接口或继承其他类,从而达到类似多重继承的效果。 5. 提供创建独立对象的方式:静态内部类可以在没有外部类实例的情况下被创建和访问,提供了一种独立创建对象的方式。这样可以在需要独立实例的场景下使用静态内部类,而不需要创建外部类的实例。 总之,静态内部类在代码组织、封装、提供特定功能和隔离实现细节等方面提供了一种有效的机制,适用于多种场景,有助于提高代码的可读性、可维护性和灵活性。
局部内部类
-
如果定义在静态方法中:则只能共享外部类静态成员
-
如果定义在非静态方法中:则能够共享外部类所有成员
-
还可以共享其所在的外部类方法中的局部变量
只是JDK8.0之前 必须加final
从8.0开始 可以不加final 但是默认还是final -
如何创建其对象:
Inner in = new Inner(); // *: 注意有位置限定 定义完成之后 所在方法结束之前
-
例如
class Outer{ int a = 1; static int b = 3; public void gogo(int c){ int d = 5; class Inner{ //局部内部类 int x = 7; public void test(){ System.out.println(a);//true (取决于gogo是否是非静态的) System.out.println(b);//true System.out.println(c);//true (取决于JDK版本 8.0之前不行 必须加final) System.out.println(d);//true (取决于JDK版本 8.0之前不行 必须加final) System.out.println(x);//true } } Inner in = new Inner(); in.test(); } }
匿名内部类
- 匿名内部类适用于那些只需要简单实现某个接口或继承某个父类的场景,它提供了一种在需要时定义临时类的方式,可以提高代码的简洁性和灵活性。但由于其局部性和生命周期的限制,它不适合用于复杂的功能实现或需要长时间使用的场景,此时应考虑使用命名的内部类。
new 父类/接口([给父类构造方法传参]){
完成抽象方法的具体实现 或者方法覆盖
}
import java.util.*;
public class TestAnonyInner{
public static void main(String[] args){
// 一个实现了Comparator接口的 但是没有名字的 类的对象
Set<Integer> set = new TreeSet<>(new Comparator<Integer>(){
@Override
public int compare(Integer i1,Integer i2){
return i2.compareTo(i1);
}
});
Collections.addAll(set,55,33,44,11,22);
System.out.println(set);
//我要降序~
}
}
-
匿名内部类能够共享外部类的哪些成员?
这不能一概而论,它可能等价于上述三种任意一种,取决于定义它的位置
Java中共享数据常用的方式有哪些
使用静态变量完成共享
public class ExecShareData1{
public static void main(String[] args){
Boy xh = new Boy();
Girl xg = new Girl();
xh.drink();
xg.drink();
}
}
class Cinema{
static Object cola = new Object();
}
class Boy{
public void drink(){
System.out.println(Cinema.cola);//静态的属性可以直接 类名. 调用
}
}
class Girl{
public void drink(){
System.out.println(Cinema.cola);
}
}
使用参数传递完成共享
- 使用构造方法
public class ExecShareData2{
public static void main(String[] args){
Object cola = new Object();
Boy xl = new Boy(cola);
Girl xq = new Girl(cola);
xl.drink();
xq.drink();
}
}
class Boy{
Object wdyl;
public Boy(Object wdyl){
this.wdyl = wdyl;
}
public void drink(){
System.out.println(wdyl);
}
}
class Girl{
Object wdyl;
public Girl(Object wdyl){
this.wdyl = wdyl;
}
public void drink(){
System.out.println(wdyl);
}
}
/*
这段代码是一个简单的Java程序,包含了三个类:ExecShareData2、Boy和Girl。
在ExecShareData2类中,创建了一个名为"cola"的对象,并且将它作为参数分别传递给了Boy和Girl类的构造函数。
Boy类和Girl类都有一个成员变量"wdyl",它们在构造函数中接收传递进来的"cola"对象,并将其赋值给自己的"wdyl"变量。
在Boy类和Girl类中,都有一个名为"drink"的方法,它们用来打印出存储在"wdyl"变量中的对象。
在ExecShareData2类的main方法中,先创建了一个Boy对象xl,然后又创建了一个Girl对象xq。接着分别调用了xl和xq的drink方法,打印出了"cola"对象。
这个程序主要展示了两个对象(Boy和Girl)共享同一个对象引用(cola)的情况。通过传递同一个对象给不同的类,可以实现跨类的数据共享。
*/
-
经常使用setter方法来传递参数,构造方法传参有时候是一个死胡同
/* 昨天我们共享数据的时候 采用了传参,但是你要明白 传参不能仅仅会依赖构造方法完成,传参的首选 永远应该是setter方法! */ public class TestPlus02{ public static void main(String[] args){ Student stu = new Student(); Teacher tea = new Teacher(); stu.setMyTeacher(tea); tea.setMyStudent(stu); } } class Student{ Teacher myTeacher;//每个学生对应一个老师 public void setMyTeacher(Teacher myTeacher){ this.myTeacher = myTeacher; } } class Teacher{ Student myStudent;//每个老师对应一个学生 public void setMyStudent(Student myStudent){ this.myStudent = myStudent; } }
使用内部类完成共享
public class ExecShareData3{
public static void main(String[] args){
Cinema wd = new Cinema();
Cinema.Boy xc = wd.new Boy();
Cinema.Girl xh = wd.new Girl();
xc.drink();
xh.drink();
}
}
class Cinema{
Object cola = new Object();
class Boy{
public void drink(){
System.out.println(cola);
}
}
class Girl{
public void drink(){
System.out.println(cola);
}
}
}
在内部类中,如何访问得到重名的在不同位置的变量
- 通过this super 关键字
public class TestPlus01{
public static void main(String[] args){
Outer.Inner in = new Outer().new Inner();
in.test();
}
}
class Outer{
int a = 3;
class Inner extends X{
int a = 5;
public void test(){
System.out.println(a);//5
System.out.println(this.a);//5
System.out.println(Inner.this.a);//5
System.out.println(Outer.this.a);//3
System.out.println(super.a);//7
System.out.println(Inner.super.a);//7
}
}
}
class X{
int a = 7;
}
数据类型的转换
public class T {
public static void main(String[] args) {
Integer num1 = new Integer(777);
Long num2 = new Long(777);
System.out.println(num1 == num2); // 不可比较的类型: Integer和Long
Double num3 = 777.0;
long num4 = 777;
System.out.println(num3 == num4); // true,long类型会自动向上级转换,转换成double
Double num5 = 5.0;
int num6 = 7;
System.out.println(num5 + num6); // 12.0 int类型会自动向上转换,转换成double -> 7.0
}
}
NaN和Infinity
public class TestPlus03{
public static void main(String[] args){
System.out.println(5/0.0);//Infinity 无穷
System.out.println(0.0/0.0);//NaN = Not a Number
double num1 = 0.0 / 0.0;
double num2 = 0.0 / 0.0;
System.out.println(num1); //NaN
System.out.println((0.0 / 0.0) == (0.0 / 0.0));
//当执行 (0.0 / 0.0) == (0.0 / 0.0) 时,实际上是在比较两个 NaN 值,根据规范,NaN 之间的比较操作始终返回 false。
//输出小
if(num1 == num2){
System.out.println("大");
}else{
System.out.println("小");
}
}
}
语法检查涉及到沿着继承关系树进行校验的 三种语法
-
==
-
instanceof
instanceof
是 Java 的一个运算符,它用于检查一个对象是否是特定类的实例或特定类的子类的实例。具体来说,
instanceof
用于判断一个对象是否属于某个类(或其子类)的实例,返回一个布尔值(true
或false
)。它的语法是:对象 instanceof 类名
其中,
对象
是要被判断的对象,类名
是要检查的类或接口的名称。 -
() 强制类型转换
/*
语法检查涉及到沿着继承关系树进行校验的 有三种语法
1.==
2.instanceof
3.() 强制类型转换
*/
public class TestPlus04{
public static void main(String[] args){
Bird poly = new Bird();
Cat kitty = new Cat();
System.out.println(poly == kitty);//不可比较的类型: Bird和Cat
System.out.println(kitty instanceof Cat);//true
System.out.println(kitty instanceof Bird);//不兼容的类型: Cat无法转换为Bird
}
}
class Animal{}
class Bird extends Animal{}
class Cat extends Animal{}