内部类
概念:一个类中又书写其他的类,包含在内的类,属于内部类
作用:
内部类的作用:让某个类只能让本类内部能够访问到,其他的类访问不到。
例如:
package com.insideClassPart;
public class Student {
private String name;
private int age;
private Address address;
// 内部类Address类,属于某个实例级别的,作为实例的属性来使用
private class Address{ // 同时通常将内部类私有
private String city;
private String country;
private String zone;
}
}
内部类分类
内部类分类为:普通内部类(实例级别),静态内部类,局部内部类,匿名内部类。
内部类的编译后的文件名格式:外部类$.内部类.class
普通内部类
实例级别,作为实例的属性来使用,依托外部类。
package com.insideClassPart;
public class Student {
public String name;
public int age;
public Address address;
// 内部类Address类,属于某个实例级别的,作为实例的属性来使用
// 普通内部类
public class Address{ // 同时通常将内部类私有 private 修饰
private String city;
private String country;
private String zone;
}
}
package com.insideClassPart;
public class Test01 {
public static void main(String[] args) {
Student stu = new Student();
stu.name = "aqua";
stu.age = 18;
// 当内部类的修饰符为 public时
stu.address = stu.new Address();
// 临时new一个Student对象,再new一个内部类对象
Student.Address address = new Student().new Address();
}
}
静态内部类
package com.insideClassPart;
// 外部类
public class Pet {
private String name;
private int age;
// 实例级别
public void eat(){
System.out.println("外部类-实例-吃饭");
}
// 静态方法
public static void sleep(){
System.out.println("外部类-静态-睡觉");
}
// 静态内部类
public static class Address{
private String country;
private String city;
// 实例方法
public void printCountry(){
// 创建外部类对象
Pet pet = new Pet();
// 访问外部类实例方法
pet.eat();
// 访问外部类属性
pet.name = "九月";
// 访问内部类属性
this.city = "杭州";
System.out.println("内部类-实例-打印国家");
System.out.println(pet.name);
System.out.println(city);
}
// 静态方法
public static void printCity(){
System.out.println("内部类-静态-打印城市");
}
}
}
package com.insideClassPart;
// 测试静态内部类
public class Test02 {
public static void main(String[] args) {
// 只要访问权限允许,可以通过类名直接访问静态内部类中方法或创建对象
Pet.Address address = new Pet.Address();
System.out.println("address = " + address);
// 访问静态内部类中的方法
address.printCountry(); // 实例级别
Pet.Address.printCity(); // 静态级别,推荐
// address.printCity(); // 静态级别 不推荐这种方式访问
}
}
局部内部类
局部内部类,首先回顾局部变量写在方法中,则局部内部类也写在方法中。
访问范围只能在这个方法内访问到。
public class Outer2 {
private String field1;
private int field2;
public void m1(){
System.out.println(field1);
System.out.println(field2);
int a = 100;
class Inner2{
private String field1;
private int field2;
public void m2(){
// a = 123 // 报错
System.out.println(a);
System.out.println("局部内部类中的m2方法");
}
}
Inner2 inner2 = new Inner2();
inner2.m2();
}
public static void main(String[] args) {
Outer2 outer2 = new Outer2();
outer2.m1();
}
}
注意:
在局部内部类中访问外部类方法中的局部变量时,此局部变量将默认以final修饰。(可通过class文件查看)。表示在局部内部类中,只能访问外部方法中的局部变量,不能修改外部方法中的局部变量;
原因:
因为 外部类中的局部变量 将随着方法的执行完毕 出栈 而内部类对象可能不会立即被回收掉,所以在局部内部类在中 修改一个已经出栈的数据 是行不通的。
匿名内部类
没有名字的内部类;
要求:必须实现一个接口或继承一个抽象类。
抽象类或接口直接new一个实现类,这个实现类就是匿名局部内部类。
// 实现接口案例
package com.insideClassPart;
public class Outer2 {
public static void main(String[] args) {
// 直接new一个实现类,这个实现类就是匿名局部内部类
A a = new A() {
@Override
public void m1() {
System.out.println("匿名内部类 " + args); // 匿名内部类对象
}
};
// 调用接口中的方法
a.m1();
}
}
// 接口
interface A {
void m1();
}
// 继承抽象类案例
package com.insideClassPart;
public class Outer2 {
public static void main(String[] args) {
// 直接new一个实现类,这个实现类就是匿名局部内部类
A a = new A() {
@Override
public void m1() {
System.out.println("匿名内部类 " + args); // 匿名内部类对象
}
};
// 调用接口中的方法
a.m1();
B b = new B() {
@Override
public void m2() {
System.out.println("匿名内部类 ");
}
};
// 调用抽象类中的方法
b.m2();
// 创建线程时,快捷方法
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类的方式实现Runnable实现类");
}
}).start();
}
}
// 接口
interface A {
void m1();
}
// 抽象类
abstract class B{
public abstract void m2();
}
通常用于创建线程时,为了省事,通过匿名内部类直接创建接口。
设计模式
设计模式来源于一个组合GOF(四人组)所著的一本 书《设计模式》,四个开发者根据经验定的一个技巧。
原则
设计模式原则
1.依赖倒置原则:程序应该依赖于抽象,而非依赖于具象。写项目时,先设计父类,然后再写子类。
2.单一职责(原则):高内聚,一个类只描述一个事物,一个方法只实现一个功能。
3.接口隔离原则:接口与接口之间,相互隔离,不应该产生过多的依赖关系。
4.里式替换原则:程序中的父类可以替换为子类,实现相同或者类似的功能(多态思想)。
5.迪米特法则:高内聚思想,类中的信息应该与本类直接关联,不应该间接关联或者没有关联。
(所有类中的事物应该直接与本类关联,不应该间接关联或者没有关联,一个类中不应该有跟本类没有关系的信息属性或方法,一个类中只写与本类有关联的代码其他的代码写在其他地方,比如测试的代码就写在一个单独的文件中)
6.开闭原则:对扩展开放,对修改源代码关闭。
7.合成复用原则:接口的组合、方法的复用、继承关系、代码的重用等等。
单例模式
单例模式又分为 饿汉单例和懒汉单例。
单例模式:在内存中只允许一个当前类的实例,即可以使用单例。
懒汉单例示例:只有在调用的时候才创建对象,也可以叫作懒加载
package com.singleLetonPart;
public class LazySingleLeton {
// 定义一个 私有静态 实例对象为空,先不new对象,懒汉单例
private static LazySingleLeton instance = null;
// 构造方法私有,才能保证内存中只有一份
private LazySingleLeton(){}
// 定义静态方法
public static LazySingleLeton getInstance(){
if (instance == null){ // 当instance为空时
instance = new LazySingleLeton(); // 创建对象
}
return instance;
}
}
package com.singleLetonPart;
public class Test01 {
public static void main(String[] args) {
// 创建对象
LazySingleLeton instance = LazySingleLeton.getInstance();
System.out.println("instance = " + instance);
}
}
饿汉单例示例:类加载时立即就创建对象
package com.singleLetonPart;
public class HungrySingleLeton {
// 上来就创建对象,饿汉单例
private static HungrySingleLeton instance = new HungrySingleLeton();
private HungrySingleLeton(){};
public static HungrySingleLeton getInstance(){
return instance;
}
}
package com.singleLetonPart;
public class Test01 {
public static void main(String[] args) {
// 创建对象
LazySingleLeton instance = LazySingleLeton.getInstance();
System.out.println("instance = " + instance);
HungrySingleLeton instance2 = HungrySingleLeton.getInstance();
System.out.println("instance2 = " + instance2);
}
}