个人整理非商业用途,欢迎探讨与指正!!
« 上一篇
定义在一个类的内部,一个类中又有一个类,被称为内部类(InnerClass),外部的称之外部类(OuterClass)
内部类的特点:
可以访问到外部类的所有成员,包括私有成员,不会破坏封装特性
内部类同样会生成对应的字节码文件(.class),名字:外部类$内部类名.class
外部类的特点:
一个java文件中可以编写多个类,但最多只能有一个类由public修饰,称为主类,主类的名称必须和文件名一致
建议:一个java文件中只编写一个类
内部类的分类:
类的成员:属性,方法,构造方法,注解,注释,代码块,内部类(可以直接写在类中的)
成员内部类,静态内部类,局部内部类,匿名内部类
类似于成员变量(属性)
只能定义非静态的属性和方法
可以无条件的访问所有外部类的成员
创建对象的语法:
内部类 对象名 = new 外部类().new 内部类();//需要导包
外部类.内部类 对象名 = new 外部类().new 内部类();//不需要导包
package com.qf;
public class OuterClass01 {
// 定义外部类的成员
String name;
protected int age;
private String hobby;
static int num;
public void abc() {
}
// 定义成员内部类
public class InnerClass01 {
// 定义属性
int a;
private int b;
public int c;
protected int d;
// 不能定义静态成员
// static int e = 10;
// 定义方法
public void show() {
// 调用自身
System.out.println(a+":"+b+":"+"c"+"d");
test();
// 调用外部类的
System.out.println(name+":"+age+":"+hobby+":"+num);
abc();
}
// 静态方法不行
/*public static void test() {
}*/
public void test() {
}
}
}
使用static修饰内部类
静态内部类中可以属性方法,静态属性方法
只能访问外部类的静态成员
创建语法
内部类 对象名 = new 外部类.内部类();
package com.qf;
public class OuterClass02 {
// 定义外部类的成员
String name;
protected int age;
private String hobby;
static int num;
public void abc() {
}
public static void def() {
}
// 定义成员内部类
public static class InnerClass02 {
// 定义属性
int a;
private int b;
public int c;
protected int d;
// 能定义静态成员
static int e = 10;
// 定义方法
public void show() {
// 调用自身
System.out.println(a+":"+b+":"+"c"+"d");
test();
// 调用外部类的静态资源
System.out.println(/*name+":"+age+":"+hobby+":"+*/num);
// abc();
def();
}
// 静态方法
public static void test() {
}
public void test1() {
}
}
}
只能定义在方法内部
特点:
定义非静态成员
可以访问外部成员
只能在方法内部创建对象
package com.qf;
public class OuterClass03 {
// 定义外部类的成员
String name;
protected int age;
private String hobby;
static int num;
public void abc() {
int m = 1;
// 局部内部类
class InnerClass03{
int a = 10;
// 不能静态成员
// static int b = 10;
public void a() {
System.out.println(name);
System.out.println(age);
System.out.println(hobby);
System.out.println(num);
System.out.println(m);
System.out.println(a);
}
}
// 局部内部类创建对象的方式
InnerClass03 c03 = new InnerClass03();
c03.a();
}
public static void def() {
}
}
匿名内部类本身就是一个对象
语法:
new 类/接口(){
//内部类 重写父类的方法
};
特点:
本身就是一个对象
匿名内部类中一般单独不定义属性和方法,因为没有意义
匿名内部类的父类一般是抽象类或者是接口
匿名内部类只能使用一次
public static void main(String[] args) {
// 匿名内部类
MyAbClass mc = new MyAbClass() {
// 方法的重写
@Override
public void test() {
System.out.println("我是匿名内部类中的");
}
};
mc.test();
// 匿名内部类
MyInter mi = new MyInter() {
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("show()...");
}
};
mi.show();
}
/**
* @author volume
* @version 1.0.0
* 该接口判断一个数是否为奇数
* */
// 函数式接口,接口中只有一个方法
public interface MyInter {
/**
* @param num传入一个数 判断这个数是否为奇数
* @return boolean true是奇数 false偶数
* */
boolean odd(int num);
}
/**
*
* @author y1538
* 调用接口的方法
*/
public class MyTest {
// 接口调用
public static void check(int num,MyInter mi) {
// 多态
boolean flag = mi.odd(num);
System.out.println(flag?"奇数":"偶数");
}
}
// 工具的调用者
public class Test01 {
// 测试环节
public static void main(String[] args) {
// 参数1为需要被判断的内容 参数2为功能
MyTest.check(12, new MyInter() {
@Override
public boolean odd(int num) {
if(num % 2 == 1) {
return true;
}
return false;
}
});
}
}
this表示当前类的对象
若调用外部类和内部类的重名属性或者方法时,需要使用this进行区分
package com.qf;
public class OuterClass04 {
int a = 10;
public void show() {
System.out.println("嗨嗨嗨");
}
// 内部类的命名符合类的命名,只要在当前类中不重名就行
class InnerClass {
int a = 20;
public void show() {
int a = 30;
System.out.println(a);
// 当前内部类中的a
System.out.println(this.a);
// 调用外部类的a
System.out.println(OuterClass04.this.a);
OuterClass04.this.show();
}
}
public static void main(String[] args) {
InnerClass ic = new OuterClass04().new InnerClass();
ic.show();
}
}
1.内部类可以更好的实现隐藏
外部类,不能使用private和protected进行修饰,但内部类可以
public class Test04 {
// 使用内部类去实现一个接口,然后实现的对应的方法为当前类所用
private class Inner implements MyInter{
@Override
public void show() {
System.out.println("hello");
}
}
// 定义获取内部类的方法
public Inner getInner() {
return new Inner();
}
public void show() {
getInner().show();
}
}
2.无条件的访问外部类的成员
私有属性和方法都能访问
3.可以帮助java完成类的多继承
通过内部类完成的
public class Test05 extends Dog{
public class Inner extends Cat{
}
// 获取名字方法
public String getName() {
return new Inner().name;
}
public String getType() {
return type;
}
}
class Dog{
String type;
}
class Cat{
String name;
}
4.避免继承和实现时方法重名
package com.qf;
public class Test06 {
class Inner01 extends A {
@Override
public void show() {
}
}
class Inner02 implements B {
@Override
public void show() {
}
}
public void inner01Show() {
new Inner01().show();
}
public void inner02Show() {
new Inner02().show();
}
}
abstract class A {
public abstract void show();
}
interface B {
void show();
}
API:Application Programming Interface
应用程序接口
Java-API中包含了java中的所有内置类及其使用方式
Object类是java中所有类的根。 每个类都有Object作为超类(父类,基类)。
所有对象(包括数组)都实现了这个类的方法。
位于继承数的最顶端
所有类都直接或者间接继承了Object类,Object类中方法可以被所有类直接访问
Object可以作为多态参数的存在
getClass方法
public final 类<?> getClass()
返回此Object的运行时类。
返回java中运行期的真实类型
package com.qf.test;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
// 使用比较运算符判断类型
System.out.println(dog instanceof Dog);
System.out.println(cat instanceof Cat);
// 所有的对象都可以调用
System.out.println(dog.getClass());
System.out.println(cat.getClass());
Scanner input = new Scanner(System.in);
System.out.println(input.getClass());
System.out.println("hello".getClass());
}
}
class Animal {
}
class Dog extends Animal{
}
class Cat extends Animal{
}
hashCode方法
public int hashCode()
返回对象的十进制地址值(哈希码)
hash值通过hash算法计算得到,通过对象地址和对象中的字符串进行计算得到
若对相同则hash一致,否则不一致
该方法建议被重写,重写的目的是为了配合equals使用
public class Demo02 {
public static void main(String[] args) {
Pig p1 = new Pig();
Pig p2 = new Pig();
Pig p3 = p1;
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p3.hashCode());
System.out.println(p1.hashCode() == p2.hashCode());
System.out.println(p1.hashCode() == p3.hashCode());
}
}
class Pig {
}
toString方法
public String toString()
返回对象的字符串表示形式。
默认为:getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
全限定名@十六进制的hash值
在使用System.out时,默认调用toString方法,直接显示地址形式
一般情况下,我们想输出对象的同时显示对象的基本信息,所以会选择重写toString方法
@Override
public String toString() {
// TODO Auto-generated method stub
return "Mouse (名字:"+name+",年龄:"+age+",牙齿:"+teeth+")";
}
package com.qf.test;
public class Demo03 {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr);
System.out.println(arr.toString());
Mouse mouse = new Mouse();
mouse.setName("苏塔");
mouse.setAge(20);
mouse.setTeeth(16);
System.out.println(mouse.toString());
System.out.println(mouse);
// String中的toString重写过了,大多数的类都重写了toString
System.out.println("hello".toString());
}
}
class Mouse {
private String name;
private int age;
private double teeth;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getTeeth() {
return teeth;
}
public void setTeeth(double teeth) {
this.teeth = teeth;
}
@Override
public String toString() {
return "Mouse [name=" + name + ", age=" + age + ", teeth=" + teeth + "]";
}
/*@Override
public String toString() {
return "Mouse (名字:"+name+",年龄:"+age+",牙齿:"+teeth+")";
}*/
}
equals方法
public boolean equals(Object obj)
默认是比较两个对象的地址的,底层使用的是==运算符
==运算符:
1.比较两个基本类型的数值是否一致
2.比较两个对象的地址是否一致
// object源码
public boolean equals(Object obj) {
return (this == obj);
}
equals方法的重写:
作用:比较两个对象的内容是否一致,添加到某种容器(集合)中会使用
equals方法的重写一般是和hashCode一起的(同时重写或者同时不重写)
认为对象地址一致了,那么他们的hashCode也需要一致
@Override
public int hashCode() {
// 定义了一个final变量为31(可以是任意值,31的重复概率是最低)
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());//结果+字符串的hash值
result = prime * result + no;//数值就直接加在里面
return result;
}
// 重写equals的意义:比较两个对象的内容是否一样
@Override
public boolean equals(Object obj) {
// 判断是否为同一个对象
if (this == obj)
return true;
// 参数为null
if (obj == null)
return false;
// 判断两个类的类型,若两对象的类型不一致
if (getClass() != obj.getClass())
return false;
// 将参数转换为对应的类型的对象(向下造型)
Person other = (Person) obj;
// 按照各个位置进行值的比较
if (name == null) {//两个字符串都是否为空
if (other.name != null)
return false;
} else if (!name.equals(other.name))//比较的是字符串的内容是否一致
return false;
if (no != other.no)//比较基本类型的值是否一直
return false;
return true;
}
finlize方法
当垃圾回收机制检查到系统垃圾时,自动调用(jvm自动调用的)
可以使用System.gc()进行手动触发,需要等待cpu有空闲时间才会进行回收
public class LaJi {
@Override
protected void finalize() throws Throwable {
System.out.println("垃圾回收机制开始运行");
// 不要删除
super.finalize();
}
public static void main(String[] args) {
LaJi lj = new LaJi();
// 手动的将对象标记为系统垃圾
lj = null;
// 手动触发垃圾回收机制 jvm会自动的调用finalize()
System.gc();
}
}