目录
1 关键字:static
如果将一个字段定义为static,每个类只有一个这样的字段。而对于非静态的实例字段,每个对象都有自己的一个副本。
例如给Eployee员工类添加一个实例字段id和一个静态字段nextId:
public class Employee {
public static int nextId = 1;
public int id;
}
每一个Employee对象都有一个自己的id字段,即如果创建1000个Employee对象,则有1000个实例字段id,分别对应每一个对象。但是只有一个静态字段nextId。
但这个类的所有实例将共享一个nextId。他属于类,而不属于任何单个的对象
- 不带static的实例变量,需要实例化才能调用,
对象.变量名;对象.方法名
-
- 如下例子:变量radius为不加staic的实例变量,即只有实例化new一个对象,才可以对象.radius进行调用。且同一个类的两个对象c1和c2也有各自的radius变量,完全不可能互相影响
- 如下例子:变量radius为不加staic的实例变量,即只有实例化new一个对象,才可以对象.radius进行调用。且同一个类的两个对象c1和c2也有各自的radius变量,完全不可能互相影响
Circle c1 = new Circle(2.0);
Circle c2 = new Circle(3.0);
System.out.println("c1的面积 = "+c1.findArea());//c1的面积 = 12.566370614359172
System.out.println("c2的面积 + "+c2.findArea());//c2的面积 + 28.274333882308138
类变量、类方法
- static修饰的静态变量,无需实例化,用类名就可调用,对象名也可以。
类.静态变量名;类.静态方法名; 对象.静态变量名;对象.静态方法名
-
- 创建Chinese类用来表示中国人,每个实例化的对象国际都为China,有几个对象就要赋值China几次,十分麻烦。可以写作静态变量,使该类的所有对象都共享国籍country这一属性。
- 创建Chinese类用来表示中国人,每个实例化的对象国际都为China,有几个对象就要赋值China几次,十分麻烦。可以写作静态变量,使该类的所有对象都共享国籍country这一属性。
public class Chinese {
public Chinese(String name, int age){
this.country = "China";
this.name = name;
this.age = age;
}
static String country;
String name;
int age;
public static void test(){
System.out.println("Chinese的类方法test");
}
public void people(){
System.out.println(this.name+"的实例方法");
}
}
Chinese p1 = new Chinese("张三",3);
System.out.println(Chinese.country);//类名调用China
System.out.println(p1.country);//China
//System.out.println(Chinese.name);
System.out.println(p1.name);//张三
//System.out.println(Chinese.age);
System.out.println(p1.age);//3
Chinese.test();//类名调用,Chinese的类方法test
p1.people();//张三的实例方法
- 用静态属性自增来统计中国人数
因为静态属性为类变量,全类对象共享。写静态变量count,需要每实例化一个对象,人数+1,可以写在构造方法里自增。
public class Chinese {
public Chinese(String name, int age){
this.country = "China";
this.name = name;
this.age = age;
count++;//人数自增
}
static String country;
static int count;
String name;
int age;
}
Chinese p1 = new Chinese("张三",3);
Chinese p2 = new Chinese("李四",4);
System.out.println("中国人数为"+Chinese.count);//2
- 类方法(静态方法)
-
- 将经常使用的“判断字符串是否为空”的判断抽取到工具类中做一个方法
-
- 注意:静态方法中,不可使用this,super,因为其表示对象
public class Utils {
public static boolean isEmpty(String str){
if(str != null && !str.equals("")){
return false;
}
return true;
}
}
String str = "234fhg";
String s = null;
System.out.println(Utils.isEmpty(str));//false
System.out.println(Utils.isEmpty(s));//true
- 静态方法中不可以调用非静态属性和方法,非静态方法可以调用静态方法
-
- 很好理解,调用类方法时不一定有实例对象 ,所以不可
package com.qx.day09;
/**
* Created with IntelliJ IDEA.
*
* @Author: xuexuezi
* @Date: 2022/08/14/23:38
* @Description:
*/
public class Circle {
public Circle(double radius) {
getName();//个人感觉这句没啥用,或许是为了对应属性初始化
this.radius = radius;
}
private double radius;
private static String name ="这是一个圆";
public static String getName(){
return name;//写不了this.name。因为静态方法中不可以出现this,super
}
public double findArea() {
return Math.PI * radius * radius;
}
public void display(){
System.out.println("name:"+getName()+"radius:"+this.radius+"Area:"+findArea());
}
}
System.out.println(Circle.getName());//这是一个圆
Circle c1 = new Circle(5.7);//name:这是一个圆radius:5.7Area:102.07034531513239
Circle c2 = new Circle(8.9);//name:这是一个圆radius:8.9Area:248.84555409084754
c1.display();
c2.display();
//本类中调用
public class Person {
private int id;
public static int total = 0;
public Person(){
total++;
id = total;
}
public static void main(String args[]){
Person Tom = new Person();
Tom.id = 0;
total = 100;//不用创建对象就可以访问静态成员
}
}
//其他类中调用
public class OtherClass {
public static void main(String args[]){
Person.total = 100;//不用创建对象就可以访问静态成员
//访问方式:类名.类属性,类名.类方法
System.out.println(Person.total);//100
Person c = new Person();
System.out.println(c.total);//101
System.out.println(c.id);//101
Person d = new Person();
System.out.println(d.total);//102
System.out.println(d.id);//102
//每创建一个对象,total++
}
}
单例(Singleton)设计模式
- 单例模式,软件的运行有且仅有一个实例化对象,(只会new一次)
-
- 使用单例模式解决什么问题?一般都是new对象太费劲,例如实例化对象的创建要消耗大量的时间和资源
- 使用单例模式解决什么问题?一般都是new对象太费劲,例如实例化对象的创建要消耗大量的时间和资源
饿汉式单例模式
- 指在有人调用类之前,先在类内部创建,并实例化一个对象,等着调用时返回即可
public class Single {
//构造方法私有化,不允许调用该类new对象
private Single(){
}
//在类中new一次私有的Single对象
private static Single single = new Single();
//返回创建好的实例对象
public static Single getInstance(){
return single;
}
}
//main中调用
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
Single s3 = Single.getInstance();
//已知equals方法比较普通类对象时,比较的是对象地址,必须得为同一个对象才相等为true
//==比较基本数据类型是内容,引用类比较的也是对象地址
System.out.println(s1.equals(s2));//true
System.out.println(s2.equals(s3));//true
System.out.println(s1 == s2);//true
System.out.println(s2 == s3);//true
懒汉式单例模式
- 指开始在类中出创建的对象为null,直到第一个人调用时,才new一个对象,之后所有调用都用这个第一次new的对象
public class Single2 {
//私有化构造,让外面不能直接new
private Single2(){
}
//创建对象为null,并不实例化
private static Single2 single2 = null;
//若是头次调用则new一个对象,
public static Single2 getInstance(){
if(single2 == null){
single2 = new Single2();
}
return single2;
}
}
Single2 s4 = Single2.getInstance();
Single2 s5 = Single2.getInstance();
Single2 s6 = Single2.getInstance();
System.out.println(s4.equals(s5));//true
System.out.println(s5.equals(s6));//true
System.out.println(s4 == s5);//true
System.out.println(s5 == s6);//true
饿汉式单例模式和懒汉式单例模式的区别,在于什么时候new这个对象
- 饿汉式,是在类加载之后,还没有人调用的时候,就先new好一个对象,以后不论谁来调用getInstance方法,都是直接返回之前new好的那个对象
- 懒汉式,是在第一次有人调用getInstance方法来new对象,以后再有人调用getInstance方法直接就返回之前第一次new好的对象
个人思考: 单例模式中创建本类对象的属性,和返回对象的方法都为static修饰?
用意应该是作为类属性和类方法,该类中只得存在一个,而且不允许外部调用new对象,所以要写为类方法。且该属性为本类实例化对象,不能通过对象.对象调用,取得该属性的方法自然也不好通过对象.方法调用得到对象。且单例设计模式本来就只有一个对象,通过类方法取得作为类属性的实例对象合情合理。
2 理解main方法的语法
- 在D盘下创建TestMain.java文件
public class TestMain {
public static void main(String[] args){
for(String s: args){
System.out.println(s);
}
}
}
左下角cmd打开命令控制符
D:
进入D盘目录
javac TestMain.java
编译TestMain类后生成TestMain.class文件
java TestMain 456 hyj 89j yhd
运行类,传参数[456,hyj,89j,yhd]
- 运行如图,打印传入的参数
3 类的成员之四:初始化块
- 普通初始化块:创建对象时隐式调用
- 静态初始化块:类加载时隐式调用
静态初始化块只调用一次(类加载时),而普通初始化块可以调用多次,随着对象的创建而加载
{
System.out.println("这是一个代码块");
}
static{
System.out.println("这是一个静态代码块");
}
- 非静态代码块
-
- 下例验证实例化对象时,程序的执行顺序为声明成员变量的默认值
String name;
—>静态代码块—>非静态的代码块—>显示构造器
- 下例验证实例化对象时,程序的执行顺序为声明成员变量的默认值
public class Person {
String name;
//显示构造器
public Person(){
this.name = "张三";
System.out.println("执行的是构造方法");
}
//非静态的代码块
{
System.out.println("执行的是非静态代码块");
}
}
public static void main(String[] args) {
Person p1 = new Person();
}
- 静态代码块
-
- 静态代码块中只能用静态属性和方法。且只会执行一次,不管new多少次对象。
public class Person {
String name;
static int age;
public Person(){
this.name = "张三";
System.out.println("执行的是构造方法");
}
//非静态的代码块
{
System.out.println("执行的是非静态代码块1");
}
{
System.out.println("执行的是非静态代码块2");
}
{
System.out.println("执行的是非静态代码块3");
}
//静态代码块
static{
//这里只能使用静态static修饰的属性和方法
age = 1;
showAge();
System.out.println("====执行的是静态代码块1====");
}
{
System.out.println("执行的是非静态代码块4");
}
static{
System.out.println("====执行的是静态代码块2====");
}
public static void showAge(){
System.out.println(age);
}
}
public static void main(String[] args) {
new Person();
new Person();
new Person();
}
- 在匿名内部类中用代码块代替构造方法
-
- 用
Student p = new Student(){};
来构造匿名内部类,为Student类的匿名子类
- 用
-
- 因为匿名内部类没有名字,不能创建对象,所以用代码块初始化
- 因为匿名内部类没有名字,不能创建对象,所以用代码块初始化
public class Student {
String name;
String schoolName;
public Student(){
this.name = "学生姓名";
this.schoolName = "学校名称";
System.out.println("执行的是构造方法");
}
public void test(){
System.out.println("Student的test方法");
}
}
public static void main(String[] args) {
// new Person();
// new Person();
// new Person();
//匿名内部类
Student p = new Student(){
//这是一个Student的匿名子类
//问题?现在想把name改成李四,但是不想动Student的代码
{
//在匿名内部类中,用代码块代替构造方法,为类属性初始化
super.name = "李四";
super.schoolName = "第一小学";
System.out.println("匿名子类中用代码块替代构造器");
}
@Override
public void test() {
System.out.println("在Student的匿名子类中重写test方法");
}
};
System.out.println(p.name+","+p.schoolName);
p.test();
}
4 关键字:final
- final修饰的变量必须显示赋值,且不可后期更改
-
- 常量名称采用全大写,多个单词用_分隔的方式
- final修饰的方法不可以被子类继承后重写该方法
- final修饰类,则该类不可被继承
public class TestPerson {
public TestPerson(){
count = 9;
}
int age;//普通变量可以不赋值
final int count;//在构造器中初始化常量也可以
final String PERSON_NAME = "哈哈";//final修饰的变量是就是全局常量
//final String PERSON_NAME;//1.错,final修饰的变量为常量,初始化时必须显示赋值
final static String NAME = "全局常量1";//final static修饰的变量为全局常量
final Person p = new Person();
//p.name = "新名字";//1.写法错误,final修饰的对象也不能修改啥
public void test(){
//PERSON_NAME = "87";//1.错,final修饰的变量为常量不可再赋值
System.out.println("普通方法test");
}
public final void test2(){
System.out.println("父类的final方法");
}
}
final class TestOverride extends TestPerson{
@Override
public void test() {
super.test();
}
// @Override
// public final void test2(){
// System.out.println("父类的final方法");
// }
//2. 错误,final修饰的方法不可被重写
}
//class TestOverride2 extends TestOverride{
//
//}//3. 错误,TestOverride被final修饰,不可被继承
final static 和 final的区别、静态常量与常量
原文链接
static+final称为全局常量
- 静态常量,编译期常量,编译时就确定值。(Java代码执行顺序,先编译为class文件,再用虚拟机加载class文件执行)
- 放于方法区中的静态常量池。
- 在编译阶段存入调用类的常量池中
- 如果调用此常量的类不是定义常量的类,那么不会初始化定义常量的类,因为在编译阶段通过常量传播优化,已经将常量存到调用类的常量池中了
final
- 常量,类加载时确定或者更靠后。
- 当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值
- 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;
- 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。但是它指向的对象的内容是可变的
public class NotInit {
public static void main(String[] args) {
//经过编译优化,静态常量已经存到NotInit类自身常量池中,不会加载ConstC
System.out.println(ConstC.str);
}
}
class ConstC{
public ConstC(){
count = 90;
System.out.println("ConstC ");
}
static{
age = 50;
System.out.println("ConstC init!");
}
public static final String str = "全局常量";
public static int age;
public int count;
}
5 抽象类
- 只要类中有一个抽象的方法,那么这个类就必须是一个抽象类。
- 或者将抽象方法的声明写为普通方法,并实现方法。类就不用作为抽象类
个人理解: - abstract不能修饰final的方法,因为final方法不能被重写。但abstract方法要被重写实现
- abstract不能修饰属性,因为属性无需实现,没有抽象的概念
- absract不能修饰私有方法,因为private修饰的方式无法在子类中用,但absract需要子类中重写方法
- abstract不能修饰构造器,因为构造器必须实现,不能抽象
- abstract不能修饰静态方法,static修饰的是静态方法,可以直接被类调用; 而abstract修饰的类中只有方法名,无方法体,不能被直接调用,故abstract不能和static一起使用
- 抽象类引用接收子类对象
问题:
1.为什么抽象类不可以使用final关键字声明?
抽象类不能被实例。抽象类是用来继承,子类必须重写父类的抽象方法,并提供方法体)
2.一个抽象类中可以定义构造器吗?
抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。
- 练习1:编写一个Employee类,声明为抽象类,包含如下三个属性:name,id,salary。提供必要的构造器和抽象方法:work()。对于Manager类来说,他既是员工,还具有奖金(bonus)的属性。请使用继承的思想,设计CommonEmployee类和Manager类,要求类中提供必要的方法进行属性访问。
- 写的过程中发现,抽象类一定要有无参构造。只写了有参构造,子类继承后报错
There is no default constructor available in 'com.qx.day09.Employee'
public abstract class Employee {
public Employee(int id, String name, String salary){
this.id = id;
this.name = name;
this.salary = salary;
}
public Employee(){
}
int id;
String name;
String salary;
public abstract void work();
}
class CommonEmplyee extends Employee{
@Override
public void work() {
System.out.println("普通员工工作");
}
public int getId(){
return id;
}
public String getNmae(){
return name;
}
public String getSalary(){
return salary;
}
}
class Manager extends Employee{
int bonus;
@Override
public void work() {
System.out.println("管理员工作");
}
public int getId(){
return id;
}
public String getNmae(){
return name;
}
public String getSalary(){
return salary;
}
public int getBonus(){
return bonus;
}
}
Employee e1 = new CommonEmployee();
CommonEmployee e2 = new CommonEmployee();
Employee e3 = new Manager();
Manager e4 = new Manager();
e1.work();
e2.work();
e3.work();
e4.work();
- 练习2
-
- 构造动物抽象类,由鱼和狗继承并实现行走方式的抽象方法
public abstract class Animal {
//设置动物行走方式
public abstract void move();
}
//三个动物类继承抽象类并重写抽象方法
class Fish extends Animal {
@Override
public void move() {
System.out.println(getClass().getName() + "的行走方式是游");
}
}
class Dog extends Animal {
@Override
public void move() {
System.out.println(getClass().getName() + "行走方式是跑");
}
}
class Brid extends Animal {
@Override
public void move() {
System.out.println(getClass().getName() + "行走方式是飞");
}
}
-
- 调用时,抽象类引用可接收自己的子类实例化对象(子类如果是抽象类,不可实例化对象)
Animal fish = new Fish();
Fish fish2 = new Fish();
fish.move();
fish2.move();
Animal dog = new Dog();
Dog dog2 = new Dog();
dog.move();
dog2.move();
Animal bird = new Brid();
Brid bird2 = new Brid();
bird.move();
bird2.move();
模板方法设计模式(TeplateMethod)
- 构造抽象类Template创建final方法getTime统计方法code执行时间,code为抽象方法,子类可以自由实现。
-
- 如子类SubTemplate定义code为一个10000次一句的循环,用getTime统计code执行时间
public abstract class Template {
public final void getTime(){
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() {
int i = 1000000;
while(i > 0){
i--;
}
}
}
SubTemplate s1 = new SubTemplate();
s1.getTime();
6 更彻底的抽象:接口(interface)
定义接口,类实现接口,接口继承接口
- 一个类同时实现两个接口
- 一个类既继承父类,又实现接口。那么先继承,再实现
接口没有构造器,抽象类有构造器。但都不可以实例化,即new一个对象
?
一个类可以实现多个接口,如果接口之间有相同的方法,那么实现的是哪个方法,还是同化了
接口的实际应用
public interface Cook {
void fry();
}
public interface Sing {
void singsing();
}
public abstract class Person2 {
int age;
String name;
String sex;
public abstract void showInfo();
}
public class TeacherSC extends Person2 implements Cook,Sing {
String course;
public void setInfo(String name, int age, String sex, String course){
super.name = name;
super.age = age;
super.sex = sex;
this.course = course;
}
@Override
public void showInfo() {
System.out.println("会唱歌会做菜的老师信息:");
System.out.println("姓名:"+name+",年龄:"+age+",性别"+sex);
System.out.println("任教课程:"+course);
fry();
singsing();
}
@Override
public void fry() {
System.out.println(super.name+"会做川菜");
}
@Override
public void singsing() {
System.out.println(this.name+"会唱流行歌");
}
}
TeacherSC t1 = new TeacherSC();
t1.setInfo("艾丽",25,"女","物理");
t1.showInfo();
接口的其他问题
- 接口可以继承接口
- 抽象类是对于一类事物的高度抽象,其中既有属性也有方法接口是对方法的抽象,也就是对一系列动作的抽象
- 当需要对一类事物抽象的时候,应该是使用抽象类,好形成一个父类
- 当需要对一系列的动作抽象,就使用接口,需要使用这些动作的类去实现相应的接口即可。
- 抽象类可以继承接口,不实现接口的所有抽象方法
- ?抽象类与接口的用处区别
如果abstract父类增加了抽象方法,子类必须增加实现该抽象方法,或将子类改为abstract,如果类已经投入使用,这样会很不方便。
可以采用父类新建接口,新增抽象方法。子类extends父类,并implements实现接口
工厂方法(FactoryMethod)和代理模式(Proxy)
- 宝马车的产品接口
public interface BWM {
//产品的信息介绍
//车的发动方式
void showInfo();
}
class BWM3 implements BWM{
@Override
public void showInfo() {
System.out.println("这个是宝马3系");
}
}
class BWM5 implements BWM{
@Override
public void showInfo() {
System.out.println("这个是宝马5系");
}
}
class BWM7 implements BWM{
@Override
public void showInfo() {
System.out.println("这个是宝马7系");
}
}
- 汽车生产工厂接口
public interface BWMFactory {
BWM productBWM();
}
class BWM3Factory implements BWMFactory{
@Override
public BWM productBWM() {
System.out.println("生产宝马3系车,new一个BWM3对象并返回");
return new BWM3();
}
}
class BWM5Factory implements BWMFactory{
@Override
public BWM productBWM() {
System.out.println("生产宝马5系车,new一个BWM5对象并返回");
return new BWM5();
}
}
class BWM7Factory implements BWMFactory{
@Override
public BWM productBWM() {
System.out.println("生产宝马7系车,new一个BWM7对象并返回");
return new BWM7();
}
}
- main中调用测试
//这是开发人员B的工作
BWM b3 = new BWM3Factory().productBWM();
b3.showInfo();
BWM b5 = new BWM5Factory().productBWM();
b5.showInfo();
BWM b7 = new BWM7Factory().productBWM();
b7.showInfo();
- 总结:通过工厂把new对象给隔离,通过产品的接口可以接受不同实际产品的实现类
7 类的成员之五:内部类
- 内部类前可用修饰符static,final,private,protected
- 例子
-
- 在内部类中修改外部类的变量内容,包括外部类的私有属性和方法
-
- 内部类不能和自己的外部类同名
-
- 在内部类中访问外部类的属性
外部类名.this.a = 80;
在内部类中访问自己的属性,this.a = 10;
- 在内部类中访问外部类的属性
-
- 在外部类中要使用自己的内部类的方法,得先new内部类对象。
内部类名 b = new 内部类名(); b.ma(); b.a;
- 在外部类中要使用自己的内部类的方法,得先new内部类对象。
//外部类和内部类有同名属性时,在内外区分两个同名属性
public class A {
private int a = 0;
public void showInfo(){
//外部类要用自己的内部类的方法,得先new内部类的对象
InnerB b = new InnerB();
System.out.println("");
b.ma();//在外部类方法中调用内部类方法
System.out.println("内外部类同名属性,内部属性a = "+ b.a);
System.out.println("内外部类同名属性,外部属性a = "+ a);
}
class InnerB{
int a = 10;//与外部类的属性名相同,怎么在内部类中区分两个同名属性
public void ma(){
a = 8;
A.this.a = 80;
System.out.println("内外部类同名属性,内部属性a = "+a);
System.out.println("内外部类同名属性,外部属性a = "+new A().a);
}
}
}
A a = new A();
a.showInfo();
-
- 内部类可以为final,private,protected
public class C {
final class InnerD{
//不可以被继承
}
//外部类只能是缺省或public,内部类四种访问权限修饰符都可以
private class InnerE extends InnerF{
}
protected class InnerF {
}
}
-
- 为static时,内部类中不能使用外部类的非static成员
-
- 内部类不是static时,内部类中的成员不可以为static,只有在外部类或者static的内部类中才可以声明static成员
public class G {
int a = 0;
static int b = 0;
static void showInfo(){
}
void showInfo2(){
}
static class InnerH{
static int g;
int h;
void show(){
//a = 9;//错误,内部类为static时,内部类中不能访问外部类的非static成员
b = 0;//访问外部类的static成员
}
}
class InnerI{
//错误写法,非static内部类不可以定义静态成员 static int I = 0;
int r;
void show(){
//内部类可以访问外部类的static成员和非static成员
a=9;
b=0;
}
}
}
-
- 为abtract类时,可以被其他内部类继承
-
- abstract内部类被同一个外部类中的内部类继承
- abstract内部类被同一个外部类中的内部类继承
public class J {
abstract class K{
int i = 0;
}
class L extends K{
void setI(int i){
i = 9;
}
}
}
//class M extends J.K{
//
//}
//class N {
// class O extends J.L{
//
// }
//
//}
-
- 内部类最大的作用,是实现类的多重继承。类似接口也是为了实现多重继承,即一个类可以实现多个接口,中间用","隔开即可
-
- 通过内部类实现多重继承的方式是,多个内部类分别继承多个不同的类,然后外部类可以随意调用内部类们继承到的方法和属性
-
- 类A想同时获得类B和类C的方法,并且重写
可以使用内部类来变相的实现类的多重继承
- 类A想同时获得类B和类C的方法,并且重写
public class Test3 {
class InnerA extends Aa{
int i;
@Override
void testA() {
//super.testA();
System.out.println("内部类InnerA继承A后,重写方法A");
}
}
class InnerB extends Bb{
}
class InnerC extends Cc{
}
private int k;
void showInfo(){
//创建内部类对象调用内部类方法
InnerA a = new InnerA();
a.testA();//直接调用内部类继承到的方法,不重写就是原方法
//或不命名直接new无名对象调用方法
new InnerA().testA();
new InnerB().testB();
new InnerC().testC();
}
}
class Aa{
void testA(){
System.out.println("方法A");
}
}
class Bb{
void testB(){
System.out.println("方法B");
}
}
class Cc{
void testC(){
System.out.println("方法C");
}
}
//main中调用
Test3 t3 = new Test3();
t3.showInfo();
匿名内部类
public class Test{
//构造匿名内部类
Person2 p = new Person2(){
{
//在匿名内部类中必须用代码块代替构造方法,因为匿名内部类没有构造
super.name = "haha";
}
int i = 0;
void showInfo2(){
}
};
}
interface Aaa{
public abstract void fun1();
}
public class Outer {
public static void main(String[] args){
new Outer().calllnner(new Aaa(){
//接口是不能new但此处比较特殊,是子类对象实现接口,只不过没有为对象取名
public void fun1(){
System.out.println("Implement for fun1");
}
});//两步写成一步了
}
public void calllnner(Aaa a){
a.fun1();
}
}
- 练习
分析类结构,有构造方法Test,main方法和内部类Inner
main中创建了类对象t。调用构造方法Test(),输出s3.a。内部类的a初值为5
创建了内部类对象r,输出r.a,即为5。