接口
- 接口中只能定义public并且是final的公共静态常量,不允许定义变量。
- 抽象类可以定义抽象方法和非抽象方法,接口中只能定义公共的,抽象的实例方法。
- 接口只能由其他接口实现继承
- 子接口继承的目的在于拥有父接口功能后添加新定义
- 任何一个非抽象类实现接口必需实现所有接口中方法(可以使用适配器,就不用都实现了)
- 接口被实现目的就是实现业务功能具体化
内部类
内部类的作用
- 内部类通过外部类访问从而被限定使用权限
- 内部类所定义功能更多时候只为外部类提供
- 内部类使某些功能使用更加安全
内部类的定义和创建
- 内部类必须定义在某个类中,所在类为其外部类
- 内部类可以使用public,protected,private访问修饰符
- 内部类可以试用abstract,final,static修饰符
- 内部类没有单独的java源文件,只有class文件
- 内部类的类文件名称规范:外部类$内部类.class例:
(1) Computer.Cpu cpu = new Computer().new Cpu();
- 如果是静态的非实例创建静态内部类,例子如下:
(1) Computer.Cpu cpu = new Computer.Cpu();
匿名类对象
- 匿名类对象就是直接实现接口。相当于创建了一个类,实现了接口,但是这个类没有名,直接写成了new 接口(){},所以叫匿名内部类。
- 匿名类对象就是没有名称类型的对象
- 匿名类对象经常作为接口或抽象类的实现
- 匿名类对象可减少接口或者抽象类实现类的定义
- 匿名类对象一定属于它实现的父级类型
静态代码块
静态代码块中的内容
- 静态代码块中允许访问静态属性
- 静态代码块中允许调用静态方法
- 静态代码块中允许定义局部变量及常量
- 静态代码块中允许定义局部类
- 静态代码块中不能访问实例属性和方法及定义方法
静态代码块的加载
- 静态代码块属于类和对象无关,随类的加载而加载
- 静态代码块在静态属性初始化后与调用构造器之前加载
- 静态代码块在加载时通常做一些静态属性或常量的赋值、调用静态方法等工作,如果想在产生任何所在类对象之前类加载时处理类信息则可以选择使用静态代码块完成
/** *1 企业级项目开发中,通常都会对数据库中的数据进行增删改查操作, 实际项目中数据库的结构(数据库表)是不同的, 这也体现了业务数据的不同, * 但是它们有共性的操作,那就是无论什么业务都会有对数据库表的增删改查功能实现,行为动作目的是相同的; 根据本单元及上个单元抽象的概念 * 及理解设计一个接口,能够提供适合对不同数据库表同样的操作的增删改查抽象方法, 定义若干个普通类实现上述接口并实现接口中的方法, 应 * 考虑以下问题: * 1)根据给定的字符串信息查询不同的表并根据实际情况返回不同类型的值; * 2)根据给定的用户名字符串信息验证此用户名在对应的数据库表中是否存在; * 3)根据给定的多种类型信息将此信息保存到对应的数据库表中; * 4)根据给定的不同类型参数删除符合条件的数据,并返回被删除了多少条数据. * 提示: 由于没有学习到正在的数据库操作, 所以具体实现抽象方法只要体现不同操作即可.从而理解接口抽象方法定义的意义所在. * 2 为了在使用上述接口的特定方法, 而不必在接口的实现类中提供不需要的方法,请在任务1的基础上为接口提供一个适配器类,改写实现类继承 * 这个适配器.从而避免在接口实现的普通类中出现不需要的方法代码实现. 以使得此类代码更加精简.只用需要的方法. * 3 在某个数据库表的查询操作中,需要使用到任务1中接口的某个方法, 但是由于本次操作很特殊,只会在整个应用中执行一次这样的操作, 为一次 * 这样的操作而实现接口或继承接口的适配器而定义一个java类感觉非常没有必要, 根据本单元内容及以上任务1和任务2 的实现, 在此基础上完成 * 对接口中目标方法的调用但不单独定义编写一个实现接口或继承接口适配器的实现代码. * 提示: 内部匿名类对象的作用!! */ package test; import adaptor.InterfacesAdaptor; import imp.SaveDatas; import imp.deleteData; import objects.Carrier; import imp.SearchCarrier; import imp.SearchUserName; import interfaces.SearchDatabase; import objects.DataHangar; import java.util.Scanner; public class Test { public static void main(String[] args) { //先来一个Scanner接收用户输入 Scanner input = new Scanner(System.in); /** * 1.1功能 1)根据给定的字符串信息查询不同的表并根据实际情况返回不同类型的值; */ //使用tag接收用户选择查询的信息 System.out.println("请输入需要查询的航母信息:名称 排水量"); String tag = input.next(); //以SearchDatabase接口为类型,实例化它的子类SearchCarrier SearchDatabase search = new SearchCarrier(); //实例化Carrier航母对象 Carrier car = new Carrier(); //调用searchCarrier方法,把整个对象作为参数传过去,接收返回值 Carrier c = search.searchCarrier(car); if (tag.equals("名称")) System.out.println(c.getCARRIERSNAME()); else if (tag.equals("排水量")) System.out.println(c.getCARRIERSWEIGHT()); /** * 1.2功能 2)根据给定的用户名字符串信息验证此用户名在对应的数据库表中是否存在; */ //请用户输入要查询的用户名 System.out.println("请输入您要查询的用户名:"); String userName = input.next(); //创建实例并调用searchUser方法,返回true或false代表有没有查询到这个用户名 SearchDatabase ser = new SearchUserName(); //使用布尔类型的e接收返回值并打印 boolean e = ser.searchUser(userName); System.out.println("系统中是否有此用户名:"+e); //实例化子类用get方法获取正确的用户名看下以便对比,现实中不会给用户看正确的用户名这样不符合安全性要求 SearchUserName ser1 = new SearchUserName(); System.out.println("正确的用户名应该是:"+ser1.getUserName()); /** * 1.3功能 3)根据给定的多种类型信息将此信息保存到对应的数据库表中; */ System.out.println("请输入您要存到数据库的用户名:"); String userName1 = input.next(); System.out.println("请输入您要存到数据库的密码:"); int pwd = input.nextInt(); System.out.println("请输入您要存到数据库的身高:"); double h = input.nextDouble(); //用接口作为类型去实例化SaveDatas对象 SearchDatabase ser2 = new SaveDatas(); //把用户输入的值传过去调用saveData方法,同时用一个DataHangar类型的对象dat接收返回值 DataHangar dat = ser2.saveData(userName1,pwd,h); //打印存储的结果 System.out.println("存到数据库的用户名是:"+dat.getUserName()); System.out.println("存到数据库的密码是:"+dat.getPwd()); System.out.println("存到数据库的身高是:"+dat.getH()); /** * 1.4功能 4)根据给定的不同类型参数删除符合条件的数据,并返回被删除了多少条数据. */ System.out.println("请输入您要删除的数据:1奇数,2偶数"); int signal = input.nextInt(); //使用接口作为类型去实例化deleteData对象 SearchDatabase ser3 = new deleteData(); //定义一个int接收调用删除方法返回的删除数据的个数 int receive = ser3.deleteData(signal); System.out.println("删除了"+receive+"个数据"); /** * 3.1功能 使用匿名类对象执行一个登陆操作 */ //定义用户名为king23,密码为123456 String n = "king23"; String p = "123456"; /** * 使用匿名类对象,把用户名和密码作为参数传给这个对象
这玩意儿真的有点绕,他把InterfacesAdaptor inte = new InterfacesAdaptor();拆开了,
等号左边放到了主方法外自定义方法的参数里,等号右边放到了主方法里调用的自定义方法参数里 */ InterfacesAdaptor(n, p,new InterfacesAdaptor() { //重写并调用父类接口中的验证密码的方法,如果和类的参数相等,返回true,验证通过 @Override public boolean validatePassword(String loginName, String pwd) { if (loginName != null && loginName.equals("king23") && pwd != null && !pwd.equals("") && pwd.equals("123456")) return YEAH; else return NOPE; } }); } //定义一个验证密码的静态方法 public static void InterfacesAdaptor(String name,String pwd,InterfacesAdaptor inte){ boolean res1 = inte.validatePassword(name,pwd); System.out.println("登录是否成功:"+res1); } }
package interfaces; import objects.Carrier; import objects.DataHangar; public interface SearchDatabase { /** * 1)根据给定的字符串信息查询不同的表并根据实际情况返回不同类型的值; * @return */ Carrier searchCarrier(Carrier carrier); /** * 2)根据给定的用户名字符串信息验证此用户名在对应的数据库表中是否存在; * 返回值是布尔类型,存在返回true,不存在返回false * @param userName * @return */ boolean YESE = true; boolean NOT = false; boolean searchUser(String userName); /** * 3)根据给定的多种类型信息将此信息保存到对应的数据库表中; */ //定义一个存储数据的方法,向DataHangar存储用户名,密码,身高三个数据 DataHangar saveData(String userName,int pwd,double h); /** * 4)根据给定的不同类型参数删除符合条件的数据,并返回被删除了多少条数据. */ int deleteData(int signal); /** * * 3 在某个数据库表的查询操作中,需要使用到任务1中接口的某个方法, 但是由于本次操作很特殊,只会在整个应用中执行一次这样的操作, 为一次 * * 这样的操作而实现接口或继承接口的适配器而定义一个java类感觉非常没有必要, 根据本单元内容及以上任务1和任务2 的实现, 在此基础上完成 * * 对接口中目标方法的调用但不单独定义编写一个实现接口或继承接口适配器的实现代码. * * 提示: 内部匿名类对象的作用!! */ boolean YEAH = true; boolean NOPE = false; boolean validatePassword(String loginName,String pwd); }
/** * 2 为了在使用上述接口的特定方法, 而不必在接口的实现类中提供不需要的方法, * 请在任务1的基础上为接口提供一个适配器类,改写实现类继承这个适配器.从而避 * 免在接口实现的普通类中出现不需要的方法代码实现. 以使得此类代码更加精简. * 只用需要的方法. */ package adaptor; import objects.Carrier; import interfaces.SearchDatabase; import objects.DataHangar; //定义一个适配器类,实现接口,并给接口所有的方法提供一个空实现 public class InterfacesAdaptor implements SearchDatabase { @Override public Carrier searchCarrier(Carrier carrier) { return null; } @Override public boolean searchUser(String userName) { return false; } @Override public DataHangar saveData(String userName, int pwd, double h) { return null; } @Override public int deleteData(int signal) { return 0; } @Override public boolean validatePassword(String loginName, String pwd) { return false; } }
/** * 这个类用来实现1.1功能 1)根据给定的字符串信息查询不同的表并根据实际情况返回不同类型的值; * 根据提供的查询信息,返回航母的参数 */ package imp; import adaptor.InterfacesAdaptor; import objects.Carrier; public class SearchCarrier extends InterfacesAdaptor { //重写接口中的抽象方法 @Override public Carrier searchCarrier(Carrier carrier) { return carrier; } }
/** * 这个类用来实现接口中查询用户名的功能 * 2)根据给定的用户名字符串信息验证此用户名在对应的数据库表中是否存在; */ package imp; import adaptor.InterfacesAdaptor; public class SearchUserName extends InterfacesAdaptor { //模拟数据库中存了一个用户名叫测试用户 private String userName = "测试用户"; @Override public boolean searchUser(String userName) { //判断如果传过来的字符串相等就返回true否则返回false if(this.userName.equals(userName) ) return YESE; else return NOT; } public String getUserName() { return userName; } }
/** * 3)根据给定的多种类型信息将此信息保存到对应的数据库表中; */ package imp; import adaptor.InterfacesAdaptor; import objects.DataHangar; public class SaveDatas extends InterfacesAdaptor { @Override public DataHangar saveData(String userName, int pwd, double h) { //实例化DataHanger对象,使用set方法把接收到的值存到这个对象的成员变量当中,最后返回这个对象 DataHangar dat = new DataHangar(); dat.setUserName(userName); dat.setPwd(pwd); dat.setH(h); return dat; } }
/** * 1.4功能 4)根据给定的不同类型参数删除符合条件的数据,并返回被删除了多少条数据. */ package imp; import adaptor.InterfacesAdaptor; public class deleteData extends InterfacesAdaptor { //定义一个数组,模拟数据库存了5个奇数和4个偶数 int arrayList1[] = {1,2,3,4,5,6,7,8,9}; int count = 0; @Override public int deleteData(int signal) { if (signal == 1){ //如果判断是奇数,count++,百度到删除数组元素操作很复杂,所以没有去实现删除操作 for (int i=0;i<arrayList1.length;i++){ if (arrayList1[i]%2==1) count++; } return count; }else if(signal == 2){ //如果判断是偶数,count++,百度到删除数组元素操作很复杂,所以没有去实现删除操作 for (int i=0;i<arrayList1.length;i++){ if (arrayList1[i]%2==0) count++; } return count; }else return 0; } }
//封装一个航母类,提供getter和setter方法 package objects; public class Carrier { private String CARRIERSNAME = "辽宁号"; private int CARRIERSWEIGHT = 65000; public String getCARRIERSNAME() { return CARRIERSNAME; } public void setCARRIERSNAME(String CARRIERSNAME) { this.CARRIERSNAME = CARRIERSNAME; } public int getCARRIERSWEIGHT() { return CARRIERSWEIGHT; } public void setCARRIERSWEIGHT(int CARRIERSWEIGHT) { this.CARRIERSWEIGHT = CARRIERSWEIGHT; } }
//封装一个数据仓库类,提供getter和setter方法 package objects; public class DataHangar { private String userName; private int pwd; private double h; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public int getPwd() { return pwd; } public void setPwd(int pwd) { this.pwd = pwd; } public double getH() { return h; } public void setH(double h) { this.h = h; } }
--------------------------------分割线-----------------------------------
内部类和静态代码块案例
package staticBlock;
//主方法 public class TestStaticBlock { public static void main(String[] args) { System.out.println(DataSourceManager.getURL()); } }
package staticBlock; public class DataSourceManager { private static final String URL; private static final String DRIVER; private static final String USER; private static final String PASSWORD; //因为是静态的常量,所以没有setter方法,只有getter方法 public static String getURL() { return URL; } public static String getDRIVER() { return DRIVER; } public static String getUSER() { return USER; } public static String getPASSWORD() { return PASSWORD; } //通过定义一个静态方法的方式去实例化静态代码块 static DataSourceManager self; private static void newInstanceOfDataSourceManager(){ self = new DataSourceManager(); } //定义一个静态代码块 static { /* static块中不允许直接定义任何方法 void m(){ }*/ //定义一个内部类 class InnerClass{ public void printMessage(){ System.out.println("我是定义在static块中的内部局部类"); } } URL = "jdbc:mysql://localhost:3306/test"; DRIVER = "com.mysql.jdbc.Driver"; USER = "root"; PASSWORD = "root"; //如果self不为空,则执行静态的方法去实例化静态代码块 if (self!=null) newInstanceOfDataSourceManager(); //实例化内部类,由于代码块在加载的时候就会被执行,所以会输出语句我是定义在static块中的内部类 InnerClass inner = new InnerClass(); inner.printMessage(); } //定义一个私有的构造器 private DataSourceManager(){ } }