您的位置:首页 > 其它

第十次课总结及思考

2016-07-11 14:50 387 查看
第十次课,主要讲了接口、内部类、枚举类、垃圾回收机制(GC)等知识。

一、接口

      1、特点:

        (1)使用interface关键字修饰;

        (2)支持多继承,如:

package interface_10th;

public class InterfaceExtends {

interface interfaceA{
int property_A = 5;
void testA();
}
interface interfaceB{
int property_B = 6;
void testB();
}
//interfaceC获得了父类的常量
interface interfaceC extends interfaceA,interfaceB{
int property_C = 7;
void testC();
}

public static void main(String[] args) {
// TODO Auto-generated method stub

System.out.println(interfaceC.property_A);
System.out.println(interfaceC.property_B);
System.out.println(interfaceC.property_C);
}

}
运行结果:
5
6
7
        2、命名:首字母为“I”。

        3、 接口中,成员变量:默认public final static修饰;

                             所有方法都是抽象方法,使用public abstract修饰
               注意点:成员变量和方法的修饰符只能用public,缺省状态下默认的也是public,不是default

        4、与抽象类的区别:

                     a.接口全都是抽象方法;

                     b.抽象类可以部分是抽象方法。

        5、用途:

                 a. 接口中可以定义变量,以方便以后调用;

                 b. 在创建实现接口的类的对象时,可以使用InterfaceName objectName = new ImplementClassName()(推荐使用)。

                 c. 实现接口方法时,必须使用public访问控制修饰符,如:

package interface_10th;

public interface Shape {

// 修饰符只能用public,注意默认的是public
abstract double calPerimeter();
public abstract String getType();

public static final String s = "123";

}


package interface_10th;

public class Exercise implements Shape{

double pi = 3.14;
double r;

public Exercise(double r) {

this.r = r;
}

@Override
public double calPerimeter() {

return 2*pi*r;
}

@Override
public String getType() {

return "圆形";
}
public double getArea() {
return pi*r*r;
}

public static void main(String[] args) {

Exercise exercise = new Exercise(10);
System.out.println(exercise.calPerimeter());
System.out.println(exercise.getArea());

//		或者可以以下面这种方式创建对象。因为接口和规范是分类的,所以推荐使用下面这种方式
Shape shape = new Exercise(1);
String s =  Shape.s;
System.out.println("接口里面的变量s = " + s);
System.out.println(shape.calPerimeter());

}

}
运行结果:
62.800000000000004
314.0
接口里面的变量s = 123
6.28

二、内部类

       1、内部类可以使用外部类的成员变量(包括私有)而不用生成外部类的对象

       2、如下面的代码所示:

public class StaticInnerClass {
private int age = 10;
class InnerClass{
private int age = 11;
void printInfo(){
//局部变量
int age = 12;
System.out.println(age);
//内部类变量
System.out.println(this.age);
//外部类变量
System.out.println(StaticInnerClass.this.age);
}
}

public static void main(String[] args) {

StaticInnerClass.InnerClass ic = new StaticInnerClass().new InnerClass();
ic.printInfo();
}

运行结果:

12
11
10
            利用this.age可以得到内部类变量,利用StaticInnerClass.this.age可以获取外部类变量。

          3、静态内部类:只能调用外部静态变量
          4、方法内的内部类:public class StaticInnerClass{<pre name="code" class="java">
private int age = 10;public static void main(String[] args) {StaticInnerClass oc = new StaticInnerClass();oc.sayHello();}// 方法内声明内部类,只能在方法内部使用public void sayHello() {//方法里面的类class Test{public
void printInfo(){//可以直接访问外部类成员变量System.out.println("访问外部类成员变量age = "+age);}}new Test().printInfo();}}

运行结果:

访问外部类成员变量age = 10

              5、匿名内部类:
                 (1)一次性使用,用来简化代码;

                 (2)前提条件:实现一个接口、父类或抽象类,如:

package innerclass_10th;

public class NoNameClass {

public static void main(String[] args) {

//做法传统
People children = new Children();
System.out.println("传统代码写法:");
children.eat();
System.out.println();

//抽象类——匿名内部类实现

//当chilren只使用一次
//匿名内部类
System.out.println("匿名内部类实现抽象类:");
People boy = new People() {

@Override
void eat() {

System.out.println("人在吃东西");
}
};
boy.eat();
System.out.println();

//接口——匿名内部类实现
System.out.println("匿名内部类实现接口:");
Animal animal = new Animal() {

@Override
public void walk() {

System.out.println("animal is walking!");
}
};
animal.walk();
System.out.println();

//需要用final修饰
final int age = 100;
//多线程
new Thread(new Runnable() {

@Override
public void run() {
System.out.println("多线程里面使用内部类:");
System.out.println("局部变量:"+age);
System.out.println("随机数:"+Math.random());
}
}).start();
}

}

abstract class People{
abstract void eat();

}

class Children extends People{
@Override
void eat() {
// TODO Auto-generated method stub
System.out.println("eat");

}
}
//接口
interface Animal{
//抽象方法
public abstract void walk();
}三、枚举类
        1、enum的全称为enumeration,是JDK 1.5中引入的的新特性

        2、使用enum定义的枚举类默认继承自java.lang.Enum,非Object

        3、使用enum定义的枚举类不能派生子类,即其他类不能继承枚举类

        4、枚举类所有实例必须放在第一行显示列出,系统自动添加public static final修饰,如果在代码中打出这三个单词会报错

        5、枚举类的构造器的访问权限控制符只能用private,缺省情况下默认也是使用private,放在所列出的实例所在的行之后

        6、EnumClass.values返回该枚举类的所有实例,是一个数组

        7、枚举类不能进行实例化,即无法通过new EnumClassName()进行实例化操作

        8、几个常用的方法:

           (1)name():返回枚举实例的名称

           (2)ordinal():返回枚举值在枚举类中的索引,从0开始

           (3)toString():类似name()

           (4)valueOf(enumType,name):返回指定枚举类中的指定名称(name)的枚举值

        具体看下面的例子:

package enum_10th;

public enum SeasonEnum {

//列出四个枚举实例-->对象、实例
SPRING,SUMMER,FALL,WINNER;
private SeasonEnum(){

}
}


package enum_10th;

import java.util.Scanner;

public abstract class EnumTest {

public static void main(String[] args) {

//用values返回该枚举类的所有对象
for (SeasonEnum seasonEnum : SeasonEnum.values()) {
//打印每一个对象,所有以下3行结果一样
//			System.out.print(seasonEnum + " ");
//			System.out.print(seasonEnum.toString() + " ");
System.out.print(seasonEnum.name() + " ");

}

//
//底层已经帮我们做好了,不用new
SeasonEnum se = SeasonEnum.SPRING;
//索引从0
System.out.println(se.ordinal());

//控制台输入一个字符串,验证是否等于某个枚举类实例
System.out.print("请输入季节:");
Scanner in = new Scanner(System.in);
String season = in.next();

SeasonEnum seTest = Enum.valueOf(SeasonEnum.class, season);

System.out.println("输入的季节:" + seTest.toString());
}

}
运行结果:
SPRING SUMMER FALL WINNER 0
请输入季节:SPRING
输入的季节:SPRING

当控制台输入的字符串在枚举类中不存在,会抛出一下异常:
SPRING SUMMER FALL WINNER 0
请输入季节:1
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant enum_10th.SeasonEnum.1
at java.lang.Enum.valueOf(Enum.java:236)
at enum_10th.EnumTest.main(EnumTest.java:38)

四、垃圾回收机制(GC)

      1、什么时候垃圾回收:花括号结束或对象的引用为null

      2、GC不会回收物理资源(例如数据库连接、网络IO等资源),只回收堆内存的对象

      3、GC无法精确控制垃圾回收的运行,合适的时候GC

      4、在回收任何对象之前,都会调用finalize(),看看能否让它”重生“

      5、对象在jvm堆区的状态:可达状态、可恢复状态、不可达状态

          (1)可达状态:存在引用变量引用这个对象。

          (2)可恢复状态:不存在引用变量引用这个对象,此时处于可恢复状态,系统正准备回收它,在此之前会先调用finalize()方法,看看里面有没有让它“重生”的机会,如果没有就会被回收。

          (3)不可达状态:对象与所有引用变量的关联被切断,永久性失去了引用,系统才会真正回收该对象所占用的资源。

       6、强制垃圾回收:静态方法:System.gc();实例方法:Runtime.getRuntime().gc();(推荐)

五、作业:

       场景:一个系统的数据库是可以随时切换的,目前支持连接MySql和SqlServer,甚至以后还有可能连接Oracle数据库

       要求:利用抽象模板的思想和接口规范的思想实现以上场景

       提示:数据库操作过程包含连接(connect),查询(query),释放(dispose),具体细节不用实现,体现思路即可。

package homework;

public interface IDao {

//连接数据库
public abstract void connect(String dbName);

//查询
public abstract void query(String dbName);

//释放
public abstract void dispose(String dbName);
}

package homework;

public abstract class DBImpt implements IDao{

@Override
public void connect(String dbName) {
// TODO Auto-generated method stub

}
@Override
public void query(String dbName) {
// TODO Auto-generated method stub
System.out.println(dbName+"正在查询...");
}
@Override
public void dispose(String dbName) {
// TODO Auto-generated method stub

}

}

package homework;

public class MySQLimpt extends DBImpt {

private String DBName;
public MySQLimpt(String dBName) {
this.DBName = dBName;
System.out.println("数据库名:" + this.DBName);
connect(DBName);
query(DBName);
dispose(DBName);
}
@Override
public void connect(String dbName) {
//		super.connect();
System.out.println(dbName+"已连接!");
}
@Override
public void query(String dbName) {
super.query(dbName);
}
@Override
public void dispose(String dbName) {
//		super.dispose(dbName);
System.out.println(dbName+"已释放!");
}
}

package homework;

public class OracleImpt extends DBImpt {

private String DBName;
public OracleImpt(String dBName) {
this.DBName = dBName;
System.out.println("数据库名:" + this.DBName);
connect(DBName);
query(DBName);
dispose(DBName);
}
@Override
public void connect(String dbName) {
//		super.connect(dbName);
System.out.println(dbName+"已连接!");
}
@Override
public void query(String dbName) {
super.query(dbName);
}
@Override
public void dispose(String dbName) {
//		super.dispose(dbName);
System.out.println(dbName+"已释放!");
}
}

package homework;

public class SQLServer extends DBImpt {

private String DBName;
public SQLServer(String dBName) {
this.DBName = dBName;
System.out.println("数据库名:" + this.DBName);
connect(DBName);
query(DBName);
dispose(DBName);
}

@Override
public void connect(String dbName) {
//		super.connect(dbName);
System.out.println(dbName+"已连接!");
}
@Override
public void query(String dbName) {
super.query(dbName);
}
@Override
public void dispose(String dbName) {
//		super.dispose(dbName);
System.out.println(dbName+"已释放!");
}
}

package homework;

import java.util.Scanner;

public class DaoFactory {

public static void main(String[] args) {

DBImpt dbImpt = null;
System.out.print("请选择数据库(1为MySQL,2为SQLServer,3为Oracle):");
Scanner scanner = new Scanner(System.in);
String input = scanner.next();
switch (input) {
case "1":

dbImpt = chooseDBImpt("MySQL");
break;
case "2":

dbImpt = chooseDBImpt("SQLServer");
break;
case "3":

dbImpt = chooseDBImpt("Oracle");
break;

default:
break;
}
}

public static DBImpt chooseDBImpt(String DBName) {

DBImpt dbImpt = null;
switch (DBName) {
case "MySQL":

dbImpt = new MySQLimpt(DBName);
if (dbImpt != null) {

return dbImpt;
}
case "SQLServer":

dbImpt = new SQLServer(DBName);
if (dbImpt != null) {

return dbImpt;
}
case "Oracle":

dbImpt = new OracleImpt(DBName);
if (dbImpt != null) {

return dbImpt;
}

default:
break;

}
return null;
}

}
运行结果:
请选择数据库(1为MySQL,2为SQLServer,3为Oracle):2
数据库名:SQLServer
SQLServer已连接!
SQLServer正在查询...
SQLServer已释放!

六、推荐两篇博文,感兴趣的读者可以参考一下:

       1、java
内存区域和GC机制

       2、java常量池概念
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息