第十次课总结及思考
2016-07-11 14:50
387 查看
第十次课,主要讲了接口、内部类、枚举类、垃圾回收机制(GC)等知识。
(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";
}
62.800000000000004
314.0
接口里面的变量s = 123
6.28
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(){
}
}
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)
2、GC不会回收物理资源(例如数据库连接、网络IO等资源),只回收堆内存的对象
3、GC无法精确控制垃圾回收的运行,合适的时候GC
4、在回收任何对象之前,都会调用finalize(),看看能否让它”重生“
5、对象在jvm堆区的状态:可达状态、可恢复状态、不可达状态
(1)可达状态:存在引用变量引用这个对象。
(2)可恢复状态:不存在引用变量引用这个对象,此时处于可恢复状态,系统正准备回收它,在此之前会先调用finalize()方法,看看里面有没有让它“重生”的机会,如果没有就会被回收。
(3)不可达状态:对象与所有引用变量的关联被切断,永久性失去了引用,系统才会真正回收该对象所占用的资源。
6、强制垃圾回收:静态方法:System.gc();实例方法:Runtime.getRuntime().gc();(推荐)
要求:利用抽象模板的思想和接口规范的思想实现以上场景
提示:数据库操作过程包含连接(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);
}
请选择数据库(1为MySQL,2为SQLServer,3为Oracle):2
数据库名:SQLServer
SQLServer已连接!
SQLServer正在查询...
SQLServer已释放!
内存区域和GC机制
2、java常量池概念
一、接口
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、什么时候垃圾回收:花括号结束或对象的引用为null2、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常量池概念
相关文章推荐
- fastjson处理接口时的一个问题
- 局域网与广域网接口标准
- RJ-45接口信号定义
- DVI 视频接口图文解析
- 如何设置域名接口
- 通过C#实现自动售货机接口
- C#中IEnumerable接口用法实例分析
- C#中实现判断某个类是否实现了某个接口
- C#隐式/显示实现接口方法详解
- C#实现两接口中同名方法实例分析
- 详解C#中的接口属性以及属性访问器的访问限制
- C#中的ICustomFormatter及IFormatProvider接口用法揭秘
- C#接口实现方法实例分析
- 基于C# 中可以new一个接口?的问题分析
- C#抽象类和接口的区别分析
- 详细解读PHP中接口的应用
- php单一接口的实现方法
- C#中类与接口的区别个人总结
- C语言接口与实现方法实例详解
- 学习JavaScript设计模式(接口)