Day10课堂笔记
标签(空格分隔):java基础
包
- 包是什么,为什么要有包?
包:就对类(.class)文件进行分类管理
思考:在同一个盘符下,我放两个完全一模一样的文件,文件名完全一样?可以吗?
看到,不可以
如果说,我非要在这里放相同的文件,你就要建立一个文件夹
定义包的注意事项有哪些?
包:package (定义包的关键字)
(1)一个java文件里面只能有一句定义包的 package
(2)定义在java这个文件的开头,class上面,必须是第一行语句
(3)如果要定义多级包,要用 “.”分割
通常来说,都是公司域名倒着书写
按模块划分
举例 : 就业班划分 services层 dao层 controller层
定义单级包
package 包名;
举例 :package heima; //单级包
举例 package com.heima
如何编译运行带包的类?
编译: javac -d . 类名.java
运行: java 包名.类名
有包和没包区别:
没定义包的时候:直接javac
没定义包的时候:直接运行 java
有定义包的时候:javac 编译没有问题
运行有定义包的时候:直接运行有问题,报了错误 java.lang.NoClassDefFoundError
直接运行 java PackageDemo也是有问题
解决方案: 在那个文件根目录,直接逐层建立文件夹,然后把.class文件放进去,回到刚才的目录,运行的时候,书写 java 包名.类名运行
以上解决方案过于麻烦,所以提出了新方案
在编译的时候 用 javac -d . 类名.java 这种,可以系统直接帮你自动生成文件夹,避免了手动创建文件夹的麻烦
解释:-d <目录> 指定放置生成的类文件的位置
. : 当前目录,这个是生成在当前目录的
举例 :这个是生成其他文件夹的 javac -d G:\A PackageDemo.java
运行时候:就在.java文件所在的目录下运行即可
不同包之间的类怎么去使用
- 如果两个不同的包名的类,在相互之间使用,如果直接用? 不可以
- 解决方案一:
在使用这个类的时候,要在使用的类前面加上包名
举例
com.heima.Student s = new com.heima.Student();
通过观察,以上调用方式非常麻烦
注意:如果要这样访问:
必须对方的类是公共的,构造方法也是公共的(public) - 解决方案二:
用import关键字解决
import 包名.类名; //开发中使用,推荐
import 包名.*; //效率太低,开发尽量少用
import com.heima.Student;
import com.heima.Person.Teacher;
import com.heima.*;
请问,第三句会导入哪些类?
留下思考,回去测试一下!
关于三个关键字的顺序问题
package,import,class有没有顺序关系?
有顺序
package 排第一
import 排中间可以有多句,没有包,import就排第一
class 最后
权限修饰符
- public 公共的
默认 :没有关键字,没有写就代表默认
private 私有的
protected : 受保护的 - 权限修饰符的比较
区别 | 本类中 | 同包不同类 | 不同包(子类) | 不同包(其他类) |
---|---|---|---|---|
private | √ | × | × | × |
默认 | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
顺序:public > protected > 默认 > private
常见的修饰符有哪些?
权限修饰符 : public private 默认 protected
状态修饰符 : static final
抽象修饰符 : abstract
常用的
成员变量 :private
构造方法 :public
成员方法 :public
组合: public static final
public static
内部类
类中类
//简单版本的内部类
class Outer{
private int num;
class Inner{
System.out.println(num); //内部类中可以访问外部类的成员(包括私有)
}
}
内部类有什么特点?
(1)可以直接访问外部类的成员
(2)外部类要访问内部类的成员,需要创建对象,格式 外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
举例 : Outer.Inner oi = new Outer().new Inner();
//这是创建一个内部类对象
在类中可以书写在成员位置的有哪些?
成员变量 构造方法 成员方法 代码块 内部类
私有成员内部类
概念:无非就是在这个内部类开头地方加一个private修饰
class Outer{
private int num;
private class Inner{
System.out.println(num); //内部类中可以访问外部类的成员(包括私有)
}
}
如果你加了private ,这个内部类就变成了私有的,这个时候不能在其他类里面直接使用
解决方案:
在这个外部类成员位置书写一个成员方法,在这个成员方法里面创建内部类对象,来调用对应的方法.
class Demo2_InnerClass {
public static void main(String[] args) {
//Outer.Inner oi = new Outer().new Inner();
//oi.method();
Outer o = new Outer();
o.print();
}
}
class Outer {
private int num = 10;
private class Inner {
public void method() {
System.out.println(num);
}
}
public void print() {
Inner i = new Inner();
i.method();
}
}
静态成员内部类
概念:其实就是把static 加在内部类class 的开头
class Outer{
private int num;
static class Inner{
public void show(){
System.out.println("show()方法");
}
public static void show2(){
System.out.println("静态show2方法");
}
}
}
需求:要访问这个非静态show方法怎么做?
在主方法里面 建立一个内部类对象,格式 :
外部类名.内部类名 对象名 = 外部类名.内部类对象();
举例 : Outer.Inner oi = new Outer.Inner();
静态修饰成员的特点:可以使用类名.成员变量/方法 来调用
需求:要访问这个非静态show方法怎么做?
直接用类名即可调用,因为是静态的:Outer.Inner.show2();
通过反编译发现,在内部类中,存在着Outer.this的指向,指向外部类的成员
Outer Inner2: 符号 表示所属的意义
在局部内部类里面要访问局部变量,我们需要对局部变量加上final关键字,让这个变量变成常量,这个时候,在编译期就可以确定这个变量的值,也就是常量.
用Xjad反编译软件,反编译可以看出,这个内部类在编译阶段就可以确定了这个值了,所以你在输出的时候,实际上就是输出了一个常量。
反编译如下:
import java.io.PrintStream;
class Outer$1Inner
{
final Outer this$0;
public void print()
{
System.out.println(10);
}
Outer$1Inner()
{
this$0 = Outer.this;
super();
}
}
- 局部内部类访问局部变量必须用final修饰
- 局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?
因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用
class Outer{
public void show(){
final int num = 10;
class Inner{
public void run(){
System.out.println(num);
}
}
}
}
匿名内部类的前提,格式及其本质分别是什么?
匿名内部类前提:
必须要有类 或者 接口
匿名内部类格式:
new 类名/接口名(){ }
匿名内部类的本质是什么?
匿名内部类的本质是一个继承了该类或者实现了该接口的匿名子类对象
class Niming_Demo {
public static void main(String[] args) {
//有名字的
/*
BaseStudent bs = new BaseStudent();
bs.run();*/
//匿名的子类对象 这种写法可以,是父类的引用指向了子类对象
Student s = new Student(){
public void run(){
System.out.println("这是一个匿名子类对象");
}
};
s.run();
}
}
class Student
{
public void run(){
System.out.println("这是一个run方法");
}
}
//有名字的子类
class BaseStudent extends Student
{
public void run(){
System.out.println("这是一个子类run方法");
}
}
匿名内部类调用多个方法时候
匿名内部类适用调用其中一个方法的时候,调用多个的时候,写法很麻烦,不推荐,但是也可以,用父类引用来指向这个匿名子类对象.如果这个匿名子类有特有的方法,还可以调用吗?这个是不可以!因为编译不过.
匿名内部类在开发中的应用?
作为参数传递
class NoNameDemo {
public static void main(String[] args) {
//需求:请用代码实现调用 method方法?
/*方案一做法:
Test t = new Test();
//通过分析,这个method需要我们传入一个Inter接口的子实现类对象
t.method(new InterImpl()); //把这个子实现类对象传进去
*/
//这是方案二: 通过方案二和方案一的对比,我们可以看出来,匿名内部类可以简化我们的代码书写,我们只需要在传参数的时候传入一个匿名内部类对象就可以实现方法的调用
//节省代码
Test t = new Test();
t.method(new Inter(){
public void add(){
System.out.println("这是匿名内部类的add方法");
}
});
}
}
interface Inter
{
public abstract void add();
}
class Test
{
public void method(Inter i){ //Inter i = new InterImpl(); 子实现类对象;
//编译看父类,运行看子类
i.add();
}
}
//方案一:写一个子实现类
class InterImpl implements Inter
{
public void add(){
System.out.println("添加方法");
}
}
匿名内部类面试题
class Test2_NoNameInnerClass {
public static void main(String[] args) {
//Outer.method().show(); //链式编程,每次调用方法后还能继续调用方法,证明调用方法返回的是对象
Inter i = Outer.method();
i.show();
}
}
//按照要求,补齐代码
interface Inter {
void show();
}
class Outer {
//补齐代码
public static Inter method() {
//有名字的子实现类 局部内部类
class InterImpl implements Inter
{
public void show(){
System.out.println("hello world!");
}
}
return new InterImpl();
}
}
/*
class Outer {
//补齐代码
public static Inter method() {
return new Inter() {
public void show() {
System.out.println("show");
}
};
}
}*/
//要求在控制台输出”HelloWorld”
匿名内部类练习题(多种方案)
/*
要求在测试类Test中创建A的对象a并调用成员方法methodA(),要求用两种方式实现
*/
public class Test2 {
public static void main(String[] args) {
/*
方案一
A a = new A();
a.methodA(new InterAImpl());*/
//方案二
/*
A a = new A();
a.methodA(new InterA(){
public void showA(){
System.out.println("这是匿名内部类的实现方式");
}
});*/
//方案三:这种是局部内部类的写法
class InnerImpl implements InterA
{
public void showA(){
System.out.println("这是局部内部类的写法");
}
}
A a = new A();
a.methodA(new InnerImpl());
}
}
//定义接口
interface InterA {
void showA();
}
class A {
public void methodA(InterA a) {
a.showA();
}
}
//方案一
class InterAImpl implements InterA
{
public void showA(){
System.out.println("这是子实现类的showA方法");
}
}