第六章 面向对象(三)
6.1 关键字:static
static关键字的使用:
1.static:静态的
2.static可以用来修饰:属性,方法,代码块,内部类
3.使用static修饰属性:静态变量
3.1属性按是否使用static修饰,又分为:静态属性VS非静态属性(实例变量) 实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其非静态属性时,不会导致其他对象中同样的属性值的修改。
静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量。其他对象调用此静态变量时,是修改过了的。
3.2static修饰属性的其他说明: 静态变量随着类的加载而加载。可以通过“类.静态变量”的方式进行调用 静态变量的加载要早于对象的创建 由于类只会加载一次,则静态变量在内存中也只会存在一份 类可以调用类变量,而对象可以嗲用类变量和实例变量。
3.3 静态属性举例:System.out;Math.PI;
4.使用static修饰方法:静态方法
4.1.随着类的加载而加载,可以通过“类.静态方法”的方式进行调用
4.2 类可以调用静态方法,对象可以调用静态方法和非静态方法
4.3 静态方法中,只能调用静态的方法和属性
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
5.static注意点:
5.1在静态方法内,不能使用this关键字,super关键字
5.2 从生命周期理解静态属性和静态方法
生命周期:类的加载,对象出生,对象消亡,类消亡
6.开发中,如何确定一个属性是否要声明为static
属性时可以被多个对象所共享的,不会随着对象的不同而不同
类中的常量也常常声明为static
开发中,如何确定一个方法是否要声明为static
操作静态属性的方法通常设置为static
工具类中的方法,习惯上声明为static,比如Math,Arrays,Collections
内存解析
public class Circle{
private double radius;
private int id;
private static int total;
private static int init=1001;
public Circle() {
id=init++;//自动赋值
total++;
}
public Circle(double radius) {
this();
//id=init++;
//total++;
this.radius=radius;
}
public static int getTotal() {
return total;
}
public int getId() {
return id;
}
public double findArea() {
return Math.PI*radius*radius;
}
}
public class classTest1 {
public static void main(String[] args) {
Circle c1=new Circle();
Circle c2=new Circle();
Circle c3=new Circle();
System.out.println(c1.getId());//1001
System.out.println(c2.getId());//1002
System.out.println(c3.getId());//1003
System.out.println(Circle.getTotal());//3
}
}
单例设计模式
单例设计模式
1.所谓类的单例设计模式,就是采取一定的方法保证在整个的系统软件中,对某个类只能存在一个对象实例
2.区分饿汉式和懒汉式
饿汉式:
坏处:对象加载时间过长
好处:饿汉式是线程安全的
懒汉式:
好处:延迟对象的创建
目前写法的坏处:线程不安全
单例模式的优点
由于单例模式只生成一个实例, 减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
饿汉式
public class classTest1 {
public static void main(String[] args) {
Bank bank1=Bank.getInstance();
Bank bank2=Bank.getInstance();
System.out.println(bank1==bank2);//true
}
}
//饿汉式1
class Bank{
//1.私有化类的构造器
private Bank() {
}
//2.内部创建类的对象
//4.要求此对象也必须声明为静态的
private static Bank instance=new Bank();
//public static final Bank instance=new Bank();
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance() {
return instance;
}
}
//饿汉式2
class Bank{
//1.私有化类的构造器
private Bank() {
}
//2.内部创建类的对象
//4.要求此对象也必须声明为静态的
private static Bank instance=null;
static{
instance=new Bank();
}
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance() {
return instance;
}
}
懒汉式
public class classTest1 {
public static void main(String[] args) {
Order o1=Order.getInstance();
Order o2=Order.getInstance();
System.out.println(o1==o2);//true
}
}
//懒汉式
class Order{
//1.私有化类的构造器
private Order() {
}
//2.内部创建类的对象,没有初始化
//4.要求此对象也必须声明为静态的
private static Order instance=null;
//3.提供公共的静态的方法,返回类的对象
public static Order getInstance() {
if(instance==null) {
instance=new Order();
}
return instance;
}
}
6.2 理解main方法的语法
main()方法的使用说明
1.main()方法作为程序的入口
2.main()方法也可以是一个普通的静态方法
3.main()方法可以作为我们与控制台交互的方式
public class classTest1 {
public static void main(String[] args) {
Main.main(new String[100]);//main静态方法的调用
classTest1 test=new classTest1 ();
test.show();//调用非静态方法
}
public void show() {
}
}
class Main{
public static void main(String[] args) {
for(int i=0;i<args.length;i++) {
System.out.println(args[i]);
}
}
}
public class classTest1 {
public static void main(String[] args) {//入口,传入string类型
for(int i=0;i<args.length;i++) {
System.out.println("******"+args[i]);
int num=Integer.parseInt(args[i]);
System.out.println("######"+num);
}
}
}
可以正常编译运行
6.3 类的成员之四:代码块
1.代码块的作用:用来初始化类,对象
2.代码块如果有修饰的话,只能使用static
3.静态代码块:
- 内部可以有输出语句;
- 随着类的加载而执行
- 作用:初始化类的信息
- 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
- 静态代码块的执行要优先于非静态代码块的执行
- 静态代码块内只能调用静态的属性,静态的方法,不能调用非静态的结构
4.非静态代码块:
- 内部可以有输出语句;
- 随着对象的创建而执行;
- 每创建一个对象,就执行一次非静态代码块
- 作用:可以在创建对象时,对对象的属性等进行初始化
- 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
- 非静态代码块内可以调用静态的属性,静态的方法,或非静态的属性,非静态的方法
public class BlockTest {
public static void main(String[] args) {
String desc=Person.desc;//hello,static block
Person p1=new Person();//hello,block
Person p2=new Person();//hello,block
}
}
class Person{
String name;
int age;
static String desc="我是一个人";
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
static {
System.out.println("hello,static block");
}
{
System.out.println("hello,block");
}
public void eat() {
System.out.println("吃饭");
}
}
对属性可以赋值的位置:
1.默认初始化
2.显式初始化/ 5.在代码块中赋值
3.构造器中的初始化
4.“对象.属性”或“对象.方法”的方式进行赋值
public class OrderTest {
public static void main(String[] args) {
Order o=new Order();
System.out.println(o.orderId);//3
//先写先执行
}
}
class Order{
{
orderId=4;
}
int orderId=3;
}
class Root{
static{
System.out.println("Root的静态初始化块");
}
{
System.out.println("Root的普通初始化块");
}
public Root(){
System.out.println("Root的无参数的构造器");
}
}
class Mid extends Root{
static{
System.out.println("Mid的静态初始化块");
}
{
System.out.println("Mid的普通初始化块");
}
public Mid(){
System.out.println("Mid的无参数的构造器");
}
public Mid(String msg){
//通过this调用同一类中重载的构造器
this();
System.out.println("Mid的带参数构造器,其参数值:"
+ msg);
}
}
class Leaf extends Mid{
static{
System.out.println("Leaf的静态初始化块");
}
{
System.out.println("Leaf的普通初始化块");
}
public Leaf(){
//通过super调用父类中有一个字符串参数的构造器
super("尚硅谷");
System.out.println("Leaf的构造器");
}
}
public class LeafTest{
public static void main(String[] args){
new Leaf();
//new Leaf();
}
}
/*
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:尚硅谷
Leaf的普通初始化块
Leaf的构造器
*/
class Father {
static {
System.out.println("11111111111");
}
{
System.out.println("22222222222");
}
public Father() {
System.out.println("33333333333");
}
}
public class Son extends Father {
static {
System.out.println("44444444444");
}
{
System.out.println("55555555555");
}
public Son() {
System.out.println("66666666666");
}
public static void main(String[] args) { // 由父及子 静态先行
System.out.println("77777777777");
System.out.println("************************");
new Son();
System.out.println("************************");
new Son();
System.out.println("************************");
new Father();
}
}
/*
11111111111
44444444444
77777777777
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
*/
6.4 关键字:final
1.final可以用来修饰的结构:类,方法,变量
2.final 用来修饰一个类:此类不能被其他类所继承。
比如:String类,System,StringBuffer
3.final 用来修饰方法,表明此方法不可以被重写
比如:Object类中的getClass();
4.final 用来修饰变量,此时的变量就称为是一个常量
- final 修饰属性,可以考虑赋值的位置有:显式初始化,代码块中的初始化,构造器中初始化
(不可以用set等其他方法来赋值,构造器调用完之后final修饰的变量就在堆空间中出现了,此时必须赋值) - final修饰局部变量:尤其是使用final修饰形参时,表明此形参是一个常量(名称大写)。当我们调用此方法时,给常量形参赋一个实参,一旦以后,就只能在方法体内使用此形参,但不能进行重新赋值。
- static final 用来修饰属性:全局常量
public class Something {
public int addone(final int x) {
//return ++x;错误
return x+1;
}
public class Something {
public static void main(String[] args) {
Other o=new Other();
new Something().addone(o);
}
public void addone(final Other o) {
//o=new Other();错误
o.i++;
}
}
class Other{
public int i;
}
小结
public static void main(String[] args){方法体}
- 权限修饰符:private 缺省 protected public–封装性
- 修饰符:static final abstract native 可以用来修饰方法
- 返回值类型:无返回值/有返回值–return
- 方法名:需要满足标识符命名的规则,规范:“见名知意”
- 形参列表:重载VS重写:参数的值传递机制:体现对象的多态性
- 方法体:来体现方法的功能
6.5 抽象类与抽象方法
abstract关键字的使用
1.可以用来修饰的结构:类,方法
2.abstract修饰类:抽象类
- 此类不能实例化
- 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
- 开发中,都会提供抽象类的方法,让子类对象实例化,完成相关操作
3.abstract修饰方法:抽象方法 - 抽象方法只有方法的声明,没有方法体
- 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
- 若子类重写了父类中的所有的抽象方法后,此子类方可实例化
- 若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰。
abstract使用上的注意点: - abstract不能用来修饰属性,构造器等
- abstract不能用来修饰私有方法,静态方法,final的方法,final的类。不能继承
静态方法要通过类来调用,有具体的实现,而abstract的方法需要重写,没有具体的实现
多态的意义也体现在抽象类,本身抽象类不能创建对象,如果不使用多态抽象类就没有意义。
public abstract class GeometricObject {
String color="white";
public GeometricObject(String color) {
super();
this.color = color;
}
public abstract double findArea();
}
public class Cylinder extends GeometricObject{
double width;
double height;
public Cylinder(double width,double height,String color) {
super(color);
this.width=width;
this.height=height;
}
@Override
public double findArea() {//表面积
return width*height;
}
}
问题1:final不能继承,而抽象类需要继承
问题2:可以定义构造器,便于子类实例化调用
问题3:可以这样理解
匿名类
非匿名类非匿名对象
匿名对象
匿名子类的对象
匿名子类的匿名对象
public class PersonTest {
public static void main(String[] args) {
Student s=new Student();
method(s);//非匿名的类非匿名的对象
method(new Student());//非匿名的类匿名的对象
//匿名子类的对象P
Person p=new Person() {
@Override
public void eat() {
}
@Override
public void walk() {
}
};
//匿名子类的匿名对象
method(new Person() {
@Override
public void eat() {
}
@Override
public void walk() {
}
});
}
public static void method(Person p) {
p.eat();
p.walk();
}
}
abstract class Person{
String name;
int age;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public abstract void eat();
public abstract void walk();
}
class Student extends Person{
String course;
public Student() {
super();
}
public Student(String name, int age, String course) {
super(name, age);
this.course = course;
}
@Override
public void eat() {
}
@Override
public void walk() {
}
}
多态的应用:模板方法设计模式
举例
代码运行时间
public class Something {
public static void main(String[] args) {
SubTemplate t=new SubTemplate();
t.spendTime();
}
}
abstract class Template{
public void spendTime() {
long start=System.currentTimeMillis();
code();
long end=System.currentTimeMillis();
System.out.println("花费的时间为:"+(end-start));
}
public abstract void code();
}
class SubTemplate extends Template{
@Override
public void code() {
for(int i=2;i<=1000;i++) {
boolean isFlag=true;
for(int j=2;j<=Math.sqrt(i);j++) {
if(i%j==0) {
isFlag=false;
break;
}
}
if(isFlag==true) {
System.out.println(i);
}
}
}
}
public class TemplateMethodTest {
public static void main(String[] args) {
BankTemplateMethod btm = new DrawMoney();
btm.process();
BankTemplateMethod btm2 = new ManageMoney();
btm2.process();
}
}
abstract class BankTemplateMethod {
// 具体方法
public void takeNumber() {
System.out.println("取号排队");
}
public abstract void transact(); // 办理具体的业务 //钩子方法
public void evaluate() {
System.out.println("反馈评分");
}
// 模板方法,把基本操作组合到一起,子类一般不能重写
public final void process() {
this.takeNumber();
this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码
this.evaluate();
}
}
class DrawMoney extends BankTemplateMethod {
public void transact() {
System.out.println("我要取款!!!");
}
}
class ManageMoney extends BankTemplateMethod {
public void transact() {
System.out.println("我要理财!我这里有2000万美元!!");
}
}
练习
public class PayrollSystem {
public static void main(String[] args) {
/*
Scanner scanner=new Scanner(System.in);
System.out.println("请输入当月的月份:");
int month=scanner.nextInt();
*/
Calendar calendar=Calendar.getInstance();
int month=calendar.get(Calendar.MONTH);//从0开始
Employee[] e=new Employee[2];
e[0]=new SalariedEmployee("曼森",new MyDate(1992,2,18),1002,10000);
e[1]=new HourlyEmployee("潘玉生",new MyDate(1993,7,4),2001,60,240);
for(int i=0;i<e.length;i++) {
System.out.println(e[i]);
double salary=e[i].earnings();
System.out.println(salary);
if((month+1)==e[i].getBirthday().getMonth()) {
System.out.println("生日快乐!");
}
}
}
}
abstract class Employee{
private String name;
private MyDate birthday;
private int number;
public abstract double earnings();
public Employee(String name, MyDate birthday, int number) {
super();
this.name = name;
this.birthday = birthday;
this.number = number;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "[name=" + name + ", birthday=" + birthday + ", number=" + number + "]";
}
public MyDate getBirthday() {
return birthday;
}
public int getNumber() {
return number;
}
}
class MyDate{
private int year;
private int month;
private int day;
public MyDate(int year, int month, int day) {
super();
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
@Override
public String toString() {
return year + "年" + month + "月" + day + "日";
}
}
class SalariedEmployee extends Employee{
private double monthlySalary;
public SalariedEmployee(String name, MyDate birthday, int number, double monthlySalary) {
super(name, birthday, number);
this.monthlySalary = monthlySalary;
}
@Override
public double earnings() {
// TODO Auto-generated method stub
return monthlySalary;
}
@Override
public String toString() {
return "SalariedEmployee" + super.toString();
}
}
class HourlyEmployee extends Employee{
private double wage;
private double hour;
public HourlyEmployee(String name, MyDate birthday, int number, double wage, double hour) {
super(name, birthday, number);
this.wage = wage;
this.hour = hour;
}
@Override
public double earnings() {
return wage*hour;
}
public String toString() {
return "HourlyEmployee" + super.toString();
}
}
6.6 接口
接口的使用
1.接口使用interface来定义
2.Java中,接口和类是并列的两个结构
3.如何定义接口:定义接口中的成员
- JDK7及以前,只能定义全局常量和抽象方法
- 全局变量:public static final的,但是书写时,可以省略不写
- 抽象方法:public abstract的
- JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法,默认方法
4.接口中不能定义构造器的!意味着接口不可以实例化
5.java开发中,接口通过(implements)的方式来使用 - 如果实现类覆盖了接口(间接和直接父类接口)中的所有抽象方法,则此类可以实例化
- 如果实现类没有覆盖接口中的所有抽象方法,则此实现类是一个抽象类
6.java类可以实现多个接口—弥补了java单继承性的局限性
格式:class AA extends BB implements CC,DD…
7.接口与接口之间可以继承,而且可以多继承
8.接口的具体使用,体现多态性
9.接口,实际上可以看成是一种规范
继承是“是不是”的关系,接口是“能不能”的关系
interface Flyable{
//全局常量
public static final int MAX_SPEED=7900;
int MIN_SPEED=1;//省略了public static final
//抽象方法
public abstract void fly();
void stop();//省略了public abstract
}
class Plane implements Flyable{
@Override
public void fly() {
}
@Override
public void stop() {
}
}
接口中的匿名对象,匿名类
public class test1{
public static void main(String[] args) {
//1.创建了接口的非匿名实现类的非匿名对象
Plane p=new Plane();
method(p);
//2.创建了接口的非匿名实现类的匿名对象
method(new Plane());
//3.创建了接口的匿名实现类的非匿名对象
Flyable f=new Flyable() {
@Override
public void fly() {
}
@Override
public void stop() {
}
};
//4.创建了接口的匿名实现类的匿名对象
method(new Flyable() {
@Override
public void fly() {
}
@Override
public void stop() {
}
});
}
public static void method(Flyable f) {
}
}
接口的应用:代理模式
public class test1 {
public static void main(String[] args) {
Network net = new ProxyServer(new RealServer());
net.browse();
}
}
interface Network {
public void browse();
}
// 被代理类
class RealServer implements Network {
@Override
public void browse() {
System.out.println("真实服务器上网浏览信息");
}
}
// 代理类
class ProxyServer implements Network {
private Network network;
public ProxyServer(Network network) {
this.network = network;
}
public void check() {
System.out.println("检查网络连接等操作");
}
public void browse() {
check();
network.browse();
}
}
public class StaticProxyTest {
public static void main(String[] args) {
Star s = new Proxy(new RealStar());
s.confer();
s.signContract();
s.bookTicket();
s.sing();
s.collectMoney();
}
}
interface Star {
void confer();// 面谈
void signContract();// 签合同
void bookTicket();// 订票
void sing();// 唱歌
void collectMoney();// 收钱
}
//被代理类
class RealStar implements Star {
public void confer() {
}
public void signContract() {
}
public void bookTicket() {
}
public void sing() {
System.out.println("明星:歌唱~~~");
}
public void collectMoney() {
}
}
//代理类
class Proxy implements Star {
private Star real;
public Proxy(Star real) {
this.real = real;
}
public void confer() {
System.out.println("经纪人面谈");
}
public void signContract() {
System.out.println("经纪人签合同");
}
public void bookTicket() {
System.out.println("经纪人订票");
}
public void sing() {
real.sing();
}
public void collectMoney() {
System.out.println("经纪人收钱");
}
}
相同点:不能实例化;都可以包含抽象方法
不同点:1.把抽象类和接口(java7,8,9)的定义,内部结构解释说明
2.类:单继承 接口:多继承
类与接口:多实现
面试题:排错
x不明确
System.out.println(super.x);
System.out.println(A.x);
排错:
ball = new Ball("Football");
//接口中的ball为常量不能再new
练习
方法一
public class InterfaceTest {
public static void main(String[] args) {
CompareCircle c1=new CompareCircle(2.3);
CompareCircle c2=new CompareCircle(3.4);
int compareValue=c1.compareTo(c2);
if(compareValue>0) {
System.out.println("c1对象大");
}else if(compareValue<0) {
System.out.println("c2对象大");
}else {System.out.println("一样大");}
}
}
interface CompareObject{
public int compareTo(Object o);
}
class Circle{
private double radius;
public Circle(double radius) {
super();
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
}
class CompareCircle extends Circle implements CompareObject{
public CompareCircle(double radius) {
super(radius);
}
@Override
public int compareTo(Object o) {
if(this==o) {
return 0;
}
if(o instanceof CompareCircle) {
CompareCircle c=(CompareCircle) o;
if(this.getRadius()>c.getRadius()) {
return 1;
}
if(this.getRadius()<c.getRadius()) {
return -1;
}else {
return 0;
}
}else {return 0;}
}
}
方法二
将radius定义为Double包装类
调用包装类中的compareTo方法
class Circle{
private Double radius;
public Circle(Double radius) {
super();
this.radius = radius;
}
public Double getRadius() {
return radius;
}
public void setRadius(Double radius) {
this.radius = radius;
}
}
class CompareCircle extends Circle implements CompareObject{
public CompareCircle(Double radius) {
super(radius);
}
@Override
public int compareTo(Object o) {
if(this==o) {
return 0;
}
if(o instanceof CompareCircle) {
CompareCircle c=(CompareCircle) o;
return this.getRadius().compareTo(c.getRadius());
}
else {return 0;}
}
}
java8接口新特性
静态方法,默认方法
public class test1 {
public static void main(String[] args) {
SubClass s=new SubClass();
//s.method1(); error
//SubClass.method1(); error
//知识点1:接口中定义的静态方法,只能通过接口来调用
CompareA.method1();
//知识点2:通过实现类的对象,可以调用接口中的默认方法
//如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
s.method2();
//SubClass.method2(); error
//知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法
//那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法
//类优先原则
s.method3();//Superclass:西安
//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法
//那么在实现类没有重写此方法的情况下,报错----接口冲突
//这就需要我们必须在实现类中重写此方法
}
}
interface CompareA {
double PI = 3.14;
public static void method1() {
System.out.println("compareA:北京");
}
public default void method2() {
System.out.println("compareA:上海");
}
default void method3() {
System.out.println("compareA:西安");
}
}
class Superclass{
public void method3() {
System.out.println("Superclass:西安");
}
}
class SubClass extends Superclass implements CompareA{
}
interface CompareB {
default void method3() {
System.out.println("compareB:西安");
}
}
class SubClass extends Superclass implements CompareA,CompareB{
@Override
public void method3() {
System.out.println("SubClass:西安");
}
//知识点5:如何在子类(实现类)的方法中调用父类,接口中被重写的方法
public void myMethod() {
method3();//调用自己定义的重写的方法
super.method3();//调用的是父类中声明的
//调用接口中的默认方法
CompareA.super.method3();
CompareB.super.method3();
}
}
6.7 类的成员之五:内部类
内部类
1.java中允许将一个类A声明在另一个类B中,则leiA就是内部类,类B称为外部类
2.内部类的分类:成员内部类(静态,非静态)VS局部内部类(方法内,代码块内,构造器内)
3.成员内部类
- 作为外部类的成员
- 可以调用外部类的结构
- 可以被static修饰
- 可以被4中不同的权限修饰
- 作为一个类:
- 类内可以定义属性,方法,构造器等
- 可以被final修饰,表示此类不能被继承。
- 可以被abstract修饰
4.关注的问题: - 如何实例化成员内部类的对象
- 如何在成员内部类中区分调用外部类的结构
- 开发中局部内部类的使用
实例化成员内部类的对象
public class test1 {
public static void main(String[] args) {
//静态成员内部类,创建实例
Person.Dog dog=new Person.Dog();
dog.show();
//非静态成员内部类,创建实例
//Person.Bird bird=new Person.Bird();
Person p=new Person();
Person.Bird bird=p.new Bird();
}
}
class Person{
//静态成员内部类
static class Dog{
public void show() {
}
}
//非静态成员内部类
class Bird{
public void sing() {
System.out.println("我是一只小鸟");
Person.this.eat();//外部类的方法
}
}
public void eat() {
}
public void method() {
//局部内部类
class AA{
}
}
{
//局部内部类
class BB{
}
}
}
public class test1 {
public static void main(String[] args) {
Test t = new Test();//5
Test.Inner r = t.new Inner();
System.out.println(r.a);//5
}
}
class Test {
public Test() {
Inner s1 = new Inner();
s1.a = 10;
Inner s2 = new Inner();
s2.a = 20;
Test.Inner s3 = new Test.Inner();
System.out.println(s3.a);
}
class Inner {
public int a = 5;
}
}
成员内部类中区分调用外部类的结构
public class test1 {
public static void main(String[] args) {
Outer a = new Outer();
Outer.Inner b = a.new Inner();
b.mb(333);
}
}
class Outer {
private int s = 111;
public class Inner {
private int s = 222;
public void mb(int s) {
System.out.println(s); // 局部变量s
System.out.println(this.s); // 内部类对象的属性s
System.out.println(Outer.this.s); // 外部类对象属性s
}
}
}
/*
333
222
111
*/
开发中局部内部类的使用
在局部内部类的方法中(比如:show)如果调用局部内部类所声明的方法(method)中的局部变量(比如num)要求此局部变量声明为final。(java8以后,可以省略final的声明)
public void method(){
int num=10;
class AA{
public void show(){
//num=20;
System.out.println(num);
}
}
}
这是因为内部类和外部类声明为两个字节码文件,内部类调用num时,是调用的副本,所以能够调用却不能修改。
匿名内部类
interface Product{
public double getPrice();
public String getName();
}
public class AnonymousTest{
public void test(Product p){
System.out.println("购买了一个" + p.getName() + ",花掉了" + p.getPrice());
}
public static void main(String[] args) {
AnonymousTest ta = new AnonymousTest();
//调用test方法时,需要传入一个Product参数,
//此处传入其匿名实现类的实例
ta.test(new Product(){
public double getPrice(){
return 567.8;
}
public String getName(){
return "AGP显卡";
}
});
}
}
//购买了一个AGP显卡,花掉了567.8