面向对象案例
面向对象(上)
1、类和对象
定义类
什么是对象?
具体的实体,比如我是一个对象,我的宠物狗二哈也是一个对象
什么是类?
类就是对象的抽象,比如我是人类,二哈是狗类
java中定义对象的语法
[修饰符] class类名
{
零到多个构造器定义...
零到多个成员方法...
零到多个方法...
}
注意,修饰符static
//定义一个Person类
public class Person(){
private int age;
private String name;
//空值构造器
public Person(){
}
//有参构造器
public Person(int age , String name){
this.age = age;
this.name=name;
}
publci void say(){
System.out.println("说话..")
}
}
//创建对象
Person p = new Person();
//给对象赋值
p.name = "张三";
p.age = 13;
//调用方法
p.say();
this的调用
public class Dog(){
//先设定一个run的方法
public void run(){
System.out.println("小狗在奔跑");
}
//在设定一个跳的方法,假定要调用run方法
/*
public void jump(){
Dog d = new Dog;
d.run;
System.out.println("小狗在跳");
}
*/
//但是上面创建类的过程可以用this来代替
public void jump(){
this.run;
System.out.println("小狗在跳");
}
}
2、方法详解
方法不能独立执行,一定是"对象.方法"或者是"类.方法"执行,如果单独存在方法,是因为省略了this
参数的传递
public class transforTest{
public static void swap(int a , int b){
int temp = a ;
a = b;
b = temp;
System.out.println("a的值为"+a+"; b的值为"+b);
}
public static void main(String args[]){
int a = 6;
int b = 9;
swap(a , b);
System.out.println("a的值为"+a+"; b的值为"+b);
}
}
/**
第一个输出显示:a值为9,b值为6
第二个输出显示:a值为6,b值为9
因为在方法中的参数不与main中的参数相同,虽然它们都叫a,并且swap方法没有返回a与b,所以在swap方法里交换后,不影响a,b的输出值
*/
方法的重载
public class Overload(){
public void test(){
System.out.println("这是一个测试方法");
}
public void test(String content){
System.out.println("传入的内容为"+ content);
}
public static void main(String args[]){
Overload o = new Overload();
o.test();
o.test("重载的方法");
}
}
/**
传入的参数不一致,导致使用的方法也不一致,这就是方法的重载
*/
3、成员变量和局部变量

成员变量与类变量的例子
class Person{
//Person类的实例变量
public String name;
//Person类的类变量
public static int eyeNum;
}
public class PersonTest{
public static void main(String[] args) {
//首先输出Person类的eyeNum,类对象进行过初始化,因此输出0
System.out.println("Person类的类变量eyeNum的初始值为" + Person.eyeNum);
//建立一个Person对象,对Person的实例变量和类变量进行赋值
Person p1 = new Person();
System.out.println("没有复制之前的类变量eyeNum的值为" + p1.eyeNum + "; 实例变量值为"+p1.name);
p1.name = "孙悟空";
p1.eyeNum = 2;
System.out.println("p1的类变量eyeNum的值为" + p1.eyeNum + "; p1的实例变量值为"+p1.name);
System.out.println("Person类的类变量eyeNum的值为" + Person.eyeNum);
//建立另外一个对象p2,因为前面对类变量进行赋值,所以直接输出值为2
Person p2 = new Person();
//eyeNum属于类的,因此输出为2,但name属于实例的,因此输出为null
System.out.println("p2的类变量eyeNum的值为" + p2.eyeNum +"p2的name的值为:"+p2.name);
}
注意:实例变量是随之对象的建立而建立的 ,两个实例对象的变量之间并没有什么关系
建议:因为类变量任何对象都可以访问,因此使用时最好以类为主调,而不是对象,这样可以避免产生歧义
局部变量
public class VariableTest {
//定义一个实例变量
public String name="李芳";
//定义一个类变量
public static double price = 98.0;
public void info(){
//局部方法的变量会覆盖重名的类变量和实例变量,且在方法结束后会被销毁
String name = "老王";
System.out.println(name);
//使用this为变量做限定则可以输出实例变量的值
System.out.println(this.name);
}
public static void main(String[] args) {
//同样的,局部变量会覆盖类变量
int price = 65;
System.out.println(price);
//使用类名做限定
System.out.println(VariableTest.price);
//运行info方法
new VariableTest().info();
}
}
4、隐藏和封装

封装举例
使用get和set封装
public class Person {
//使用private修饰,让这些变量都隐藏起来
private String name;
private int age;
//提供方法来操作变量
public void setName(String name){
//执行校验程序
if (name.length() > 6 || name.length() < 2){
System.out.println("您的命名不符合规范");
return;
}else{
this.name = name;
}
}
public String getName() {
return this.name;
}
public void setAge(int age){
//执行校验程序
if (age > 150|| age < 0){
System.out.println("您的输入不符合规范");
return;
}else{
this.age = age;
}
}
public int getAge() {
return this.age;
}
}
操作对象的age和name
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
p.setName("王小二");
p.setAge(7);
System.out.println("输出set后的名字:"+p.getName() + "; 输出set后的年龄:"+ p.getAge());
}
}
Java的常用包
java.lang:这个包下包含的Java语言的核心类,如Stirng、Math、System和Thread,这个包无需import导入,系统会自动导入
java.util:这个包下包含了Java的大量工具类和集合框架类/接口,如Arraylist\List\Set等
java.net:这个包下包含了网络编程相关的类\接口
java.io:这个包下包含了输入\输出相关的类\接口
java.text:这个包下包含了一些Java格式化相关的类
java.sql:这个包下包含了JDBC数据库相关的类\接口
5、构造器
将所有的实例变量实行初始化
public class ConstructorTest {
public String name;
public int count;
//自定义构造器
public ConstructorTest(String name , int count){
this.count=count;
this.name = name;
}
public static void main(String[] args) {
ConstructorTest c = new ConstructorTest("狼王",12);
System.out.println(c.count);
System.out.println(c.name);
}
}
构造器的重载
public class ConstructorTest {
public String name;
public int count;
public int age;
//自定义构造器
public ConstructorTest(String name , int count){
this.count=count;
this.name = name;
}
public ConstructorTest(String name , int count,int age){
this(name,count);
this.age = age;
}
public static void main(String[] args) {
ConstructorTest c = new ConstructorTest("狼王",12,43);
System.out.println(c.count);
System.out.println(c.name);
System.out.println(c.age);
}
}
6、类的继承
子承父类,子类拥有父类的全部成员变量和方法
例子
public class Fruit {
public double weight;
public String name="水果";
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public void info(){
System.out.println("我是一个水果,重"+weight+"g");
}
}
public class Apple extends Fruit{
public static void main(String[] args) {
Apple a = new Apple();
a.setWeight(91.0);
a.info();
}
}
父类不变,子类重写方法
public class Apple extends Fruit{
public void info(){
System.out.println("重写父类的方法");
}
public static void main(String[] args) {
Apple a = new Apple();
a.info();
}
}
super关键字的作用
public class Apple extends Fruit{
public void info(){
System.out.println("重写父类的方法");
}
public void replay(){
System.out.println(super.name);
super.info();
}
public static void main(String[] args) {
Apple a = new Apple();
a.weight = 98.0;
a.info();
//调用方法输出“水果”和执行父类info()方法
a.replay();
//输出“水果”
System.out.println(((Fruit)a).name);
System.out.println("=========replay方法结束以后重新赋值===============");
a.name = "苹果";
System.out.println(a.name);
}
}
super可以访问被子类隐藏的父类实例变量和方法,不仅如此,super还可以继承父类构造器
class Base{
public double size;
public String name;
public Base(double size , String name){
this.size = size;
this.name = name;
}
}
public class Sub extends Base{
public String color;
public Sub(double size, String name , String color) {
super(size, name);
this.color = color;
}
public static void main(String[] args) {
Sub s = new Sub(5.6 , "测试对象","红色");
System.out.println(s.size + "--"+s.color+"--"+s.name);
}
}
7、多态
运行时的状态和编译时的不一致
class BaseClass {
public String name = "父类的名字";
public void info(){
System.out.println("父类的的方法");
}
public void test(){
System.out.println("父类即将被覆盖的方法");
}
}
public class SubClass extends BaseClass {
public String name = "子类的名字";
public void test(){
System.out.println("子类覆盖父类的方法");
}
public void sub(){
System.out.println("子类的普通方法");
}
public static void main(String[] args){
System.out.println("=====================父类===================");
BaseClass baseClass = new BaseClass();
System.out.println(baseClass.name);
baseClass.info();
baseClass.test();
System.out.println("=====================子类===================");
SubClass subClass = new SubClass();
System.out.println(subClass.name);
subClass.sub();
subClass.test();
System.out.println("=====================多态===================");
BaseClass p = new SubClass();
//将输出的是父类的实例变量
System.out.println(p.name);
//执行的是当前类的test方法
p.test();
//下面的方法失效,因为编译时是BaseClass类,没有提供sub()方法
//p.sub();
//因此可以强行转换
SubClass s = (SubClass) p;
s.sub();
}
}
例子中的p编译时的类型是BaseClass,运行时类型是SubClass
强行转换
public class Test {
public static void main(String[] args) {
double d = 13.4;
long l = (long)d;
System.out.println(l);
int in = 5;
//试图把一个数值类型的变量转换为boolean类型,下面代码编译出错
//编译时会提示:不可转类型
//boolean b = (boolean)in;
Object obj = "hello";
//obj变量编译时类型为Object,Object与String类型存在继承关系,可以强制类型转换
//而且obj变量的实际类型是String,所以运行时也能通过
String objstr = (String)obj;
System.out.println(objstr);
//定义一个ObjPri变量,编译时类型为Object,实际类型为Integer
Object objPri = new Integer(5);
//objPri变量的编译类型为Object,实际运行类型为Integer
//Object与Integer存在继承关系
//可以强制类型转换,而objPri变量的实际类型是Integer
//所以下面代码引发ClassCastException异常
//String str = (String)objPri;
//但是可以用instanceof进行判断是否可以成功转换
if (objPri instanceof String){
String str = (String)objPri;
}else {
System.out.println("不可以强制转换");
}
}
}
8、组合
组合案例
import org.w3c.dom.ls.LSOutput;
class Animal{
private void beat(){
System.out.println("心脏在跳动");
}
public void breath(){
beat();
System.out.println("呼吸~~~~");
}
}
class Bird {
private Animal a;
public Bird(Animal a){
this.a = a;
}
public void breath(){
a.breath();
}
public void fly(){
System.out.println("鸟会飞");
}
}
class fish{
private Animal a;
public fish(Animal a){
this.a = a;
}
public void breath(){
a.breath();
}
public void swim(){
System.out.println("鱼会游");
}
}
public class CompileTest {
public static void main(String[] args) {
//需要显示创建被组合的对象
Animal a1 = new Animal();
Bird b = new Bird(a1);
b.breath();
b.fly();
//需要显示创建被组合的对象
Animal a2 = new Animal();
fish f = new fish(a2);
f.breath();
f.swim();
}
}
9、初始化块

初始化块代码无需输入参数,可以更好地提高代码的复用性
实际上,初始化块代码是一个假象,经过Javac编译后,会还原到没有构造器中
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("Java");
System.out.println("执行Leaf的构造器");
}
}
public class Test{
public static void main(String[] args) {
new Leaf();
new Leaf();
}
}
面向对象(下)
1、Java8的增强包装类

自动装箱,自动拆箱
public class AutoBoxingUnboxing {
public static void main(String[] args) {
//直接把一个基本类型变量赋给Integer对象
Integer inObj =5 ;
//直接把一个boolean类型变量赋给一个Object类型
Object boolObj = true;
//直接把一个Integer对象赋给int类型的变量
int it = inObj;
if (boolObj instanceof Boolean) {
//先把Object对象 对象强制类型转换为Boolean类型,再赋给boolean变量
boolean b = (Boolean)boolObj;
System.out.println(b);
}
}
}
类型转换
public class Primitive2String {
public static void main(String[] args){
//把一个String类型转换为Int类型
String instr = "123";
int in = Integer.parseInt(instr);
System.out.println(in);
System.out.println("==========================");
//把String类型转换为float类型
String floatstr = "123.432";
float fs = Float.parseFloat(floatstr);
System.out.println(fs);
System.out.println("==========================");
//把float类型转换为String类型
float f1 = 124.65f;
String f2 = String.valueOf(f1);
System.out.println(f2);
System.out.println("==========================");
//把一个double变量转换为Sting变量
double d = 132.4;
String s = String.valueOf(d);
System.out.println(d);
System.out.println("==========================");
//把一个boolean转换为String变量
boolean b = true;
String bl = String.valueOf(b);
System.out.println(bl);
System.out.println("==========================");
}
}
注意Integer的范围
Integer ina = 2;
Integer inb = 2;
System.out.println(ina == inb)//输出true
Integer inc = 128;
Integer ind = 128;
System.out.println(inc == ind)//输出false
//因为系统把-128~127之间的整数自动装箱成Integer实例,并放入了一个数组缓存起来,在[-128,127]自动装箱实际上指的是同一个数组元素,所以相等。但是在范围外,系统总是重新创建一个实例,两个实例不相等。
Java8的无符号运算
public class UnsignedTest {
public static void main(String[] args) {
byte b = -3;
//将byte类型的-3转换为无符号整数
System.out.println("byte类型的-3对应的无符号整数"+Byte.toUnsignedInt(b));
//指定使用16进制解析无符号整数
int val = Integer.parseUnsignedInt("ab",16);
System.out.println(val);//输出171
//将-12转换为无符号int性,然后转换为16进制的字符串
System.out.println(Integer.toUnsignedString(-12,16));
//将两个数转换为无符号整数后相除
System.out.println(Integer.divideUnsigned(-2,3));
//将两个数转换为无法呼号整数后求余
System.out.println(Integer.remainderUnsigned(-2,7));
}
}
2、处理对象
toString
toString是一个“自我描述”的方法,当程序员打印该对象时,系统将会输出该对象的“自我描述”信息,用以告诉外界该对象具有的状态信息
import org.w3c.dom.ls.LSOutput;
class Apple{
private String color;
private double weight;
public Apple(){
}
public Apple(String color , double weight){
this.weight = weight;
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Apple{" +
"color='" + color + '\'' +
", weight=" + weight +
'}';
}
}
public class ToStringTest {
public static void main(String[] args) {
Apple a = new Apple("红色",5.7);
System.out.println(a);
}
}
== 和equals
== : 如何两个变量是基本类型变量,且都是数值类型(不一定要求数据类型严格相同),只要两个变量的值相等,就将返回true。对于应用比那辆,只有他们指向同一个对象时,才会返回true。
equals:提供自定义相等的标准
当使用new String("hello")时,JVM会先使用常量池来管理"hello"常量,再调用String类的构造器来创建一个新的String对象。新建的String对象被保存在堆内存中。也就是说new String("hello")实际上产生了两个字符串对象
3、类成员
类成员有:成员变量、成员方法、构造器、初始化块、内部类(接口、枚举)
当使用实例来访问类成员是,实际上依然是委托该类来访问类成员,因此即使某个实例为null,它也可以访问它所属的类的类成员,例如下面代码:
public class NullAccessStatic {
private static void test(){
System.out.println("static修饰的方法");
}
public static void main(String[] args) {
NullAccessStatic S = null;
S.test();
}
}
4、final修饰符
final成员变量
final修饰的成员变量必须有程序员显示地指定初始值,没有final修饰的成员变量系统会赋默认值
public class FinalVariableTest {
//定义成员变量时指定默认值,合法
final int a = 6;
//下面变量将在构造器或初始化块中分配初始值
final String str;
final int c ;
final static double d;
//不能打印没有初始化的值
//final int age;
//下面代码将出错:
// public static void main(String[] args){System.out.println(age)}
//既没有指定默认值,有没有在初始化块,构造器中指定初始值
//下面定义的ch实例变量时不合法的
//final char ch;
//初始化块,可对没有指定默认值的实例变量指定初始值
{
//在初始化块中为实例变量指定初始值
str = "hello";
//定义a实例变量时已经指定了默认值
//不能为a重新赋值,因此下面赋值语句非法
//a = 9;
}
//静态初始化块,可对没有指定默认值的类变量指定初始值
static {
//在静态初始化块中位类变量指定初始值,合法
d = 5.6;
}
//构造器,可对即没有指定默认值,有没有在初始化块中指定初始值的实例变量指定初始值
public FinalVariableTest(){
//如果在初始化块中已经对str指定了初始值
//那么在构造器中不能对final变量重新赋值
//str="java";
c = 5;
}
public void changeFinal(){
//普通方法不能为final修饰的成员变量赋值
//d =1.2;
//不能再普通方法中位final成员变量指定初始值
//ch = 'a';
}
public static void main(String[] args) {
FinalVariableTest f = new FinalVariableTest();
System.out.println(f.a);
System.out.println(f.d);
System.out.println(f.c);
}
}
局部变量
public class FinalLoalVariableTest {
public void test(final int a ){
//不能对形参赋值,下面语句非法
// a = 7;
System.out.println("这个衬衫的价格是"+ a + "元");
}
public static void main(String[] args) {
final int b ;
b = 8 ;
//下面语句非法
// b = 10;
FinalLoalVariableTest s = new FinalLoalVariableTest();
s.test(2);
}
}
final修饰基本类型变量和引用类型变量的区别
class Person{
private int age;
public Person(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public class FinalTest {
public static void main(String[] args) {
final int[] Arri = {1 , 2, 3 ,4, 5, 6};
//可以对Arri内的值进行赋值
Arri[2] = 4;
System.out.println(Arri[2]);
//但是不能对Arri进行赋值
//Arri = 1;
final Person p = new Person(24);
//可以对age重新赋值
p.setAge(54);
System.out.println(p.getAge());
//但时对p重新赋值是非法的
//p = null;
}
}
宏替换
public class FinalLocalTest {
public static void main(String[] args) {
//定义一个局部变量
final int a = 5;
System.out.println(a);
}
}
/**
* 程序定义了一个局部final变量,并在定义时赋予初始值为5,对这个程序来说,a根本不存在,当执行System.out.println(a);时,
* 实际执行System.out.println(a);
*/
fianl修饰符的一个重要用途就是定义"宏变量",编一个群会把程序中用到宏变量的值直接替换成该变量的值
public class FinalReplaceTest {
public static void main(String[] args) {
final int a = 9;
int a1 = 9;
//如果被富于的表达式只是基本的算是表达式或者字符串连接运算,没有访问普通变量,或者调用方法
//那么Java编译器同样会将这种final变量当成“宏变量”
final String c1 = "java";
String test = c1 + a;
String test2 = c1+a1;
final String c2 = "java" + 9;
//因为c3调用了方法,所以不会再编译时就确定下来
final String c3 = "java" + String.valueOf(9);
System.out.println(c1 == "java");
System.out.println(test == "java9");
System.out.println(test2 == "java9");
System.out.println(c2 == "java9");
System.out.println(c3 == "java9");
}
}
final方法
public class FinalMethodTest {
public final void test(){
}
}
class sub extends FinalMethodTest{
//将引发编译错误,因为不能重写final方法
public void test(){};
}
虽然不能重写fianl方法,但是当final方法用private修饰时,子类可以创建和父类同名的方法,以达到"重写"的效果
private class FinalMethodTest {
public final void test(){
}
}
class sub extends FinalMethodTest{
//将引发编译错误,因为不能重写final方法
public void test(){};
}
实例访问类成员时,实际上依然是委托给该类来访问类成员,因此即使某个实例为null,它也可以访问它所属的类的类成员,
final类
java.lang.Math就是一个final类,可以用final修饰后变得不可继承
不可变类
创建一个不可变类
public class Address {
private final String detail;
private final String postCode;
//在构造器里初始化两个实例变量
public Address(){
this.detail = "";
this.postCode = "";
}
public Address(String detail , String postCode){
this.detail =detail;
this.postCode = postCode;
}
public String getDetail() {
return detail;
}
public String getPostCode() {
return postCode;
}
//重写equals()方法,判断链各个对象是否相等
public boolean equals(Object obj){
if(this == obj){
return true;
}
if (obj != null && obj.getClass() == Address.class){
Address ad = (Address)obj;
//当detail和postCode相等时,可认为两个Address对象相等
if (this.getDetail().equals(ad.getDetail())
&& this.getPostCode().equals(ad.getPostCode())){
return true;
}
}
return false;
}
public int hashCode(){
return detail.hashCode() + postCode.hashCode()*31;
}
}
5、抽象类
public abstract class SpeedMeter {
//转速
private double turnRate;
public SpeedMeter(){}
//把返回这轮半径的方法定义成抽象方法
public abstract double getRadius();
public void setTurnRate(double turnRate){
this.turnRate = turnRate;
}
//定义计算速度的通用算法
public double getSpeed(){
return Math.PI*2*getRadius()*turnRate;
}
}
public class CarSpeedMeter extends SpeedMeter {
public double getRadius(){
return 0.28;
}
public static void main(String[] args) {
CarSpeedMeter csm = new CarSpeedMeter();
csm.setTurnRate(15);
System.out.println(csm.getSpeed());
}
}
6、接口
接口和抽象类的区别
接口类似于整个系统的总纲,指定了系统各个模块应该遵循的标准
抽象类作为多个子类的共同父类,它所体现的是一种模板式设计
- 接口只能包含抽象方法和默认方法,不能为普通方法提供方法实现;抽象类则完全可以包含普通方法
- 接口里不能定义静态方法;抽象类可以定义静态方法
- 接口里不包含构造器抽象类里可以包含构造器,抽象类的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作
- 接口里不能包含初始化块;但抽象类则完全可以包含初始化块
- 一个类最多只能有一个父类,包括抽象类;但一个类可以直接实现过个接口,通过实现多个接口可以弥补Java单继承的不出
接口的继承
interface interfaceA
{
int PROP_A = 5;
void testA();
}
interface interfaceB{
int PROP_B = 6;
void testB();
}
interface interfaceC extends interfaceA ,interfaceB{
int PROP_C = 7;
void test();
}
public class InterfaceExtendsTest {
public static void main(String[] args) {
System.out.println(interfaceC.PROP_A);
System.out.println(interfaceC.PROP_B);
System.out.println(interfaceC.PROP_C);
}
}
7、内部类
非静态内部类
public class Cow {
private double weight;
//外部类的两个重载的构造器
public Cow(){}
public Cow(double weight ){
this.weight = weight;
}
//定义一个非静态内部类
private class CowLeg{
//非静态内部类的两个实例变量
private double length;
private String color;
//非静态内部类的两个重载构造器
public CowLeg(){}
public CowLeg(double length , String color){
this.color = color;
this.length = length;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
//非静态内部类的实例方法
public void info(){
System.out.println("当前牛腿的颜色是:" +
color + ",高"+ length);
//直接访问外部类的private修饰的成员变量
System.out.println("本牛腿所在奶牛重"+ weight);
}
}
public void test(){
CowLeg c1 = new CowLeg(1.12, "黑白相间");
c1.info();
}
public static void main(String[] args) {
Cow cow = new Cow(322.1);
cow.test();
}
}
如果外部类成员变量与内部类成员变量同名,可以用this、外部类类名.this作为鉴定来区分
内部类与外部类的关系
public class Outer {
private int outProp = 9 ;
class Inner{
private int inProP = 5;
public void acessOutProp(){
//非静态内部类可以访问外部类的成员变量
System.out.println(outProp);
}
}
//外部类不能访问内部类的成员变量
public void test(){
//System.out.println(inProp);
//如果要访问内部类的实例比那辆,必须显示创建内部对象
System.out.println("内部类的inProp值"+ new Inner().inProP);
}
public static void main(String[] args) {
//这样只是创建了外部类对象,没有创建内部类对象
Outer out = new Outer();
out.test();
}
}
注意事项:
- 不允许在外部类的静态成员中直接使用费静态内部类
- 不能在非静态内部类定义静态成员
静态内部类
public class StaticInnerClassTest {
private int prop1 = 5;
private static int prop2 = 9;
static class StaticInnerClass{
//静态内部类可以包含静态成员
private static int age;
public void accessOutProp(){
//下面代码出现错误
//静态内部类无法访问外部类的实例变量
//System.out.println(prop1);
//下面代码正常
System.out.println(prop2);
}
}
}
静态内类的调用
public class AccessStaticInnerClass {
static class StaticInnerClass{
private static int prop1 = 5;
private int prop2= 9;
}
public void accessInnerProp(){
System.out.println(StaticInnerClass.prop1);
System.out.println(new StaticInnerClass().prop2);
}
public static void main(String[] args) {
AccessStaticInnerClass a = new AccessStaticInnerClass();
a.accessInnerProp();
}
}
使用内部类
out为外部类,in为内部列
out.in i = new out().new in();
匿名内部类
abstract class Device{
private String name;
public abstract double getPrice();
public Device(){}
public Device(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class AnonymousInner {
public void test(Device d){
System.out.println(d.getName() +"-------"+ d.getPrice());
}
public static void main(String[] args) {
AnonymousInner a = new AnonymousInner();
//调用有参数的构造器创建Device匿名实现类的对象
a.test(new Device("电子示波器")
{
public double getPrice() {
return 78.2;
}
});
//调用无参数的构造器创建Device匿名实现类对象
Device d = new Device() {
//初始化块
{
System.out.println("匿名类的初始化块");
}
public double getPrice() {
return 76.4;
}
//重写父类的实例方法
public String getName(){
return "键盘";
}
};
a.test(d);
}
}
9、枚举类
enum SeasonEnum{
//在第一行列出4个枚举实例
SPRING,SUMMER,FALL,WINTER;
}
public class EnumTest{
public void judge(SeasonEnum s){
//switch 语句里的表达式可以使枚举值
switch (s){
case SPRING:
System.out.println("春暖花开");
break;
case SUMMER:
System.out.println("夏天");
break;
case FALL:
System.out.println("秋天");
break;
case WINTER:
System.out.println("冬天");
break;
}
}
public static void main(String[] args) {
//枚举类默认有一个values()方法,返回枚举类的所有实例
for (SeasonEnum s : SeasonEnum.values()){
System.out.println(s);
}
//使用枚举实例时,可通过EnumClass.variable形式类访问
new EnumTest().judge(SeasonEnum.SPRING);
}
}
使用枚举类创建构造器
enum Gender{
//此处的枚举值必须调用对应的构造器来创建
MALE("男"),FEMALE("女");
private final String name;
private Gender(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class GenderTest {
public static void main(String[] args) {
Gender g1 = Gender.valueOf("MALE");
System.out.println(g1 + "代表:" + g1.getName());
Gender g2 = Gender.valueOf("FEMALE");
System.out.println(g2 + "代表:" + g2.getName());
}
}
实现枚举类的接口
interface GenderDesc{
void info();
}
enum Gender implements GenderDesc{
//此处的枚举值必须调用对应的构造器来创建
MALE("男"),FEMALE("女");
private final String name;
private Gender(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public void info() {
System.out.println("这是用于定义性别的接口");
}
}
public class GenderTest {
public static void main(String[] args) {
Gender g1 = Gender.valueOf("MALE");
System.out.println(g1 + "代表:" + g1.getName());
Gender g2 = Gender.valueOf("FEMALE");
System.out.println(g2 + "代表:" + g2.getName());
}
}
枚举类与抽象方法
public enum Operation {
PLUS{
public double eval(double x ,double y){
return x + y;
}
},
MINUS{
public double eval(double x ,double y) {
return x - y;
}
},
TIMES {
public double eval(double x, double y) {
return x * y;
}
},
DIVIDE{
public double eval(double x ,double y) {
return x / y;
}
};
//为枚举类定义一个抽象方法
//这个抽象方法由不同的枚举类提供不同的实现
abstract double eval(double x , double y);
public static void main(String[] args) {
System.out.println(Operation.PLUS.eval(3,4));
System.out.println(Operation.MINUS.eval(5,4));
System.out.println(Operation.TIMES.eval(3,4));
System.out.println(Operation.DIVIDE.eval(3,4));
}
}

浙公网安备 33010602011771号