零基础学习java------day10------带包编译,权限修饰符,内部类,调式,junitTest
0. 带包编译
解决使用notepad++编写的java类中如果有package的解决方案,如下代码
package com._51doit.test; class HelloWorld{ public static void main(String[] args){ System.out.println("hello world"); } }
第一种(手动式)
先使用javac 命令运行,得到编译后的.class文件
在当前.java所在的文件夹下。手动创建(文件夹),然后把.class 文件拷贝到文件夹中
运行命令: java 包名.类名
第二种(能自动生成包名)
编译命令:java -d 空格.空格 文件名.java(编译完会产生包名)
运行命令:java 包名.类名
导包:import 全类名(包名加类名)
顺序:package import class
1. 权限修饰符
(1)public可以在不同包其他类使用(即跨包使用),例
下图为包的结构图
由图可知,AuthDemo.java所在的包为auth,而AuthTest所在的包为day10,两个类也无继承关系
AuthDemo代码如下
package com._51doit.javase.day10.auth; public class AuthDemo { String name = “张三”; public static void print() { System.out.println("public跨包可以使用"); } }
AuthTest代码如下
package com._51doit.javase.day10.auth;
import com._51doit.javase.day10.auth.AuthDemo;
public class AuthDemo {
public static void main(String[] args) {
AuthDemo.print();
}
}
运行结果:public跨包可以使用
但若去掉AuthDemo类的public修饰符,则会出现报错,如下图
(2)protectes:修饰方法和变量
可以在不同包的子类中访问,可以使用super关键字,创建子类的对象访问(创建父类的对象无法访问)
当将AuthDemo类中成员变量的修饰符改为protected,在AuthTest中调用发现调用不了,这个时候就要将AuthTest类继承AuthDemo类(即不同包子类),创建子类对象即可调用name属性,代码如下
package com._51doit.javase.day10; import com._51doit.javase.day10.auth.AuthDemo; class AuthTest extends AuthDemo{ public static void main(String[] args) { AuthDemo.print(); // AuthDemo a = new AuthDemo(); // a.name; AuthTest a = new AuthTest(); System.out.print(a.name); } }
注意 1. 在此创建父类对象不可调用name属性,必须是子类对象
2. 不能单独使用 a.name(报错Syntax error, insert "VariableDeclarators" to complete LocalVariableDeclaration,因为a.name此处相当于常量,应该定义一个数据类型去接收它,如String name = a.name)
(3)修饰外部类的修饰符:
public (default) final abstract
2. 内部类
定义:定义在类内部的类,内部类可以直接访问外部类的成员,包括私有。外部类要访问内部类的成员,必须创建对象
2.1 成员内部类
1. 无限制的访问外部类中的成员,包括静态成员和私有成员
2. 成员内部类不能定义静态成员(原因,静态成员先于成员出现,所以成员内部类不可能有静态成员)
3. 如何创建内部类的对象:
外部类名.内部类名 对象名=new 外部类名().new 内部类名();
4. 如何在内部类中访问外部类中同名的成员
外部类名.this.成员
案例:
1 public class MemberInnerClass { 2 public static void main(String[] args) { 3 OuterClass.InnerClass inner = new OuterClass().new InnerClass(); 4 inner.show(); 5 System.out.println(inner.a); 6 } 7 } 8 class OuterClass{ 9 private String name = "张三"; 10 static int age = 10; 11 String a = "xyz"; 12 class InnerClass{ 13 String a = "acx"; 14 public void show() { 15 String a = "def"; 16 System.out.println(a); 17 System.out.println(this.a); 18 System.out.println(OuterClass.this.a); 19 System.out.println(name); 20 System.out.println(age); 21 } 22 } 23 }
2.2 局部内部类
局部内部类:定义在方法中或者是代码块中的类
1. 局部内部类只能在方法中被认识
2. 局部内部类不能使用public private protected 修饰符修饰(内部成员作用域在定义时就有范围,是所在的大括号内)
3. 在jdk1.7之前,局部内部类中访问的变量必须用final修饰,1.7之后可以不加
public class InnerClassDemo2 { public static void main(String[] args) { new OuterClass2().method(); } } class OuterClass2{ public void method(){ int a = 10;// 此处a不能用权限修饰符修饰 class InnerClass2{ public void show() { System.out.println(a); } } new InnerClass2().show();//局部内部类只能在方法中被认识,所以只能在方法中创建对象 } }
2.3 静态内部类(参考博客https://www.cnblogs.com/a8457013/p/8078826.html)
静态内部类:用static修饰的内部类
1. 静态内部类中既可以定义静态成员,也可以定义非静态的成员
2. 有静态成员(变量和方法)的内部类,一定是静态内部类
3. 如何调用静态内部类红的成员
静态成员: 外部类名.内部类名.静态成员
非静态成员: new 外部类名.内部类名().非静态成员
public class InnerClassDemo3 { public static void main(String[] args) { System.out.println(OuterClass3.InnerClass3.a); //调用静态常量 System.out.println(new OuterClass3.InnerClass3().b);//调用非静态常量 } } class OuterClass3{ static class InnerClass3{ static int a = 10; int b = 100; } }
2.4 匿名内部类(非常重要)
匿名对象:new 类名()
匿名内部类:
本质: 实现接口或者继承了(抽象)类的子类(其本质就是一个对象)
格式
new 接口/类(){
重写或实现的方法
}
要求:见到接口或者接口类就能写出匿名内部类
案例1
正常情况下,我们实现接口方法是定义一个类去继承子类然后再雷利实现这个接口,但这样很麻烦,又要创建子类又要创建对象,如下
1 public class NoNameClassDemo { 2 String name = "abc"; 3 public static void main(String[] args) { 4 InterfaceClass i = new InterfaceClass(); //创建子类对象 5 i.test(); 6 } 7 } 8 // 定义一个接口 9 interface interfaceA{ 10 public void test(); 11 } 12 // 定义接口的子类实现接口 13 class InterfaceClass implements interfaceA{ 14 public void test() { 15 System.out.println("五环,你比四环多一环"); 16 } 17 }
匿名类可以很好的解决这个问题,代码如下
public class NoNameClassDemo { String name = "abc"; public static void main(String[] args) {// 定义匿名函数此处也可以将匿名函数赋值给变量,如a,就可以用a.test()调用方法 new interfaceA() { public void test() { System.out.println("六环,你比五环多一环"); } }.test(); } } // 定义一个接口 interface interfaceA{ public void test(); }
同理,类也是一样
案例2
接口当数据类型传参(实质是父类的引用指向子类),接口不能创建对象,所以只能传其子类对象
public class NoNameInnerClass { public static void main(String[] args) { show(new FF()); // 此处传参是传接口的子类对象,接口不能创建对象 } public static void show(CC c) { c.test(); } } interface CC{ void test(); } class FF implements CC{ public void test() { System.out.println("哈哈,傻了吧"); }
此处也可以用匿名类来写,如下
public class NoNameInnerClass { public static void main(String[] args) { CC c = new CC() { public void test() { System.out.println("哈哈,傻了吧"); } }; show(c); // 此处传参是传接口的子类对象,接口不能创建对象 } public static void show(CC c) { c.test(); } } interface CC{ void test(); }
练习
3.junitTest
单元测试:
我们现在要执行一个方法,只能从main方法中开始,有一定的弊端;必须创建对象才能调用非静态方法
使用junittest可以不通过main方法让我们的程序直接执行
使用方式:
引入工具类
1.手动添加jar包(class文件的压缩包)
项目上右键--->build Path--->config build path
add extern jar- 找到需要用的jar 包, apply
使用:
在要执行的方法(非静态的)上,添加一个注解@Test
执行:
右键->run as - >junit test
使用elipse 中集成好的junit:
在包上右键-> new -> others
4. debug(断点调试)
用于追踪代码,能够直观的看到代码执行到每一步的结果
1. 加断点(一般从加载方法体中开始追踪),就是行号的左边,双击即可
2. 以debug的模式启动程序
右键->debug as->java application
控制代码的执行:
下一步: f6
进入方法: f5
跳出方法: f7:
进入下一个断点: f8