常用类
一、内部类
1.1 基本概念
在类的内部定义的类,叫做内部类。
分为:
成员内部类
静态内部类
局部内部类
匿名内部类
public class Outter { // 在类的内部定义的类 class Inner{ } }
在类的内部定义类,一般还是封装思想的体现,可以将该类定义为私有类。
在一个类中,可以定义四种情况的变量,对应四种内部类,使用方式也相似
public class Outter { String s1; // 成员变量(实例变量)、属性 static String s2; // 静态属性,类属性 public void m1() { String s3 = new String("aaa"); // 局部变量 System.out.println(new String("hello")); // 匿名变量 } }
1.2 成员内部类【了解】
成员内部类是直接在类的内部定义的普通类。
不能定义静态属性
不能定义静态方法
在内部类的方法中,如果要调用外部类的属性,可以直接使用,但是如果内部类有同名属性或局部变量,可以使用外部类的名称.this.属性名。
在外部类的静态方法中,不能直接创建成员内部类的对象
由于成员内部类的功能有缺陷(不能定义静态属性,不能定义静态方法),一般很少使用。
public class Outter { String name; // 成员变量(实例变量)、属性 // 成员内部类 class Inner{ String name; // 不能定义静态属性 // public static String s; public void m1() { System.out.println(Outter.this.name); System.out.println(name); } // 不能定义静态方法 // public static void m2() {} } public void m3() { Inner inner = new Inner(); } public static void m2() { // Inner inner = new Inner(); // 在外部类的静态方法中,不能直接创建成员内部类的对象 } } public class Demo1 { public static void main(String[] args) { Outter outter = new Outter(); outter.name = "aaa"; // System.out.println(outter.name); Outter.Inner inner = outter.new Inner(); inner.name = "bbb"; inner.m1(); // 必须先创建外部类的对象才能创建内部类的对象 Outter.Inner inner1 = new Outter().new Inner(); } }
1.3 静态内部类【重点】
静态内部类是在类的内部定义的静态类。使用方式与普通类一样,一般在项目中使用静态内部类来体现封装的特征。
public class Outter1 { public static String name; public static class Inner1{ public String a; // 可以定义属性 public static String name; // 可以定义静态属性 public void m1() { // 可以定义普通方法 } public static void m2() {// 可以定义静态方法 } } public void m1() { new Inner1(); // 可以在普通方法中创建对象 } public static void m2() { new Inner1();// 可以在静态方法中创建对象 } } public class Demo2 { public static void main(String[] args) { Outter1.Inner1 inner = new Outter1.Inner1(); inner.a = "aaa"; } }
1.4 局部内部类【了解】
在类的方法中定义的类称为局部内部类。
不能定义静态成员和静态方法
不能在类前面添加private、public等关键字
必须在方法中定义后立即使用,否则出了作用域范围会无效
public class Outter2 { public void m1() { class Inner{ // 不能定义静态成员和静态方法 private String name = "aaa"; public void m2() { System.out.println(name); } } Inner in = new Inner(); in.m2(); } }
1.5 匿名内部类【重点】
当需要将一个抽象类或者接口创建对象时,会要求继承该抽象类或者实现接口才可以创建对象。如果需要直接对该抽象类或接口创建对象,并且只使用一次,可以使用匿名内部类的方式。
public interface MyInterface { void m1(); } public abstract class MyClass { // public abstract void m1(); } public class Person { public void use(MyInterface m) { m.m1(); } } public class Demo1 { public static void main(String[] args) { // 创建一个接口对象的同时实现,匿名内部类 MyInterface m = new MyInterface() { @Override public void m1() { System.out.println("m1"); } }; m.m1(); // 使用抽象类创建匿名内部类 // MyClass m1 = new MyClass() { // @Override // public void m1() { // System.out.println("m1==="); // } // }; // // m1.m1(); // 如果接口或抽象类没有抽象方法,匿名内部类相对奇怪 MyClass m1 = new MyClass() {}; // 如果方法要传入一个接口或抽象类的对象,可以使用匿名内部类 Person p = new Person(); p.use(new MyInterface() { @Override public void m1() { System.out.println("m1"); } }); // jdk1.8中的lambda表达式 // p.use(() -> System.out.println("m1")); } }
二、Object类
Object类是所有类的父类,无论是否直接继承。
2.1 getClass()
得到对象的实际类型,一般用来比较两个对象是否同一个类的对象。
也可以通过类名.class来得到类型。
public class Demo1 { public static void main(String[] args) { Animal a = new Dog(); Dog d = new Dog(); if(a instanceof Dog) { System.out.println("a对象是Dog类的对象"); } // 判断对象是否某个类型 if(a.getClass() == Dog.class) { System.out.println("a对象是Dog类的对象"); } // 判断是否同一个类型的对象 if(a.getClass() == d.getClass()) { System.out.println("a对象和d对象是同一类型"); } // 得到类名 System.out.println(a.getClass().getName()); // 得到短类名 System.out.println(a.getClass().getSimpleName()); } }
2.2 hashCode()
返回对象的十进制的hash码值,使用哈希算法根据对象的地址或者字符串或数字计算出来的int型的值。
自定义类的对象hashCode默认返回对象的地址。
一般情况下需要重写hashCode方法,以便更好的利用hash算法。
注意:hashCode并不唯一,必须保证相同的对象具备相同的hashCode,尽量保证不同对象有不同的hashCode。
public class Student { private String id; private String name; private int age; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } }
2.3 equals方法
用来比较两个对象是否相同。
默认是比较地址,在项目中如果需要比较两个对象是否相同,应该重写equals方法。
public class Student { private String id; private String name; private int age; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { // 如果地址相同 if (this == obj) return true; // 如果比较对象为空 if (obj == null) return false; // 如果不是同一个类型 if (getClass() != obj.getClass()) return false; Student other = (Student) obj; // 如果id属性为空 if (id == null) { if (other.id != null) return false; // 如果id属性不相同 } else if (!id.equals(other.id)) return false; return true; } }
注意:equals方法和hashCode方法应该一起重写。
2.4 toString()方法
当将对象作为字符串使用或输出时,会自动调用toString方法,而该方法默认输出hashCode值(地址),没有意义,应该重写toString以便输出对象信息。
public class Student { private String id; private String name; private int age; @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
public class Demo3 { public static void main(String[] args) { Student s1 = new Student("1001", "你开心", 18); System.out.println(s1); String s = s1 + "===="; System.out.println(s); } }