1,package和import:
-
package:声明包
- 作用:避免类名的冲突
- 同包中的类不能同名,不同包中的类可以同名
- 类的全称:包名.类名,包名常常有层次结构
- 建议:包名所有字母都小写
-
import:导入类(写在package下)
-
同包中的类可以直接访问,不同包中的类不能直接访问,若想访问:
- 先import导入类,再访问类-----------建议
- 类的全称------------------------------------太繁琐、不建议
-
2, 访问控制修饰符:----------------------作用:保护数据的安全
-
public:公开的,任何类
-
private:私有的,本类
-
protected:受保护的,本类、派生类、同包类
-
默认的:什么也不写,本类、同包类-------------------------java不建议默认权限
注意:
- 类的访问权限只能是public或默认的
- 类中成员的访问权限如上4种都可以
- 访问权限由高到低依次为:public>protected>默认的>private
package ooday05;
//访问控制修饰符的演示
public class Aoo {
public int a; //任何类
protected int b; //本类、派生类、同包类
int c; //本类、同包类
private int d; //本类
void show(){
a = 1;
b = 2;
c = 3;
d = 4;
}
}
class Boo{ //演示private
void show(){
Aoo o = new Aoo();
o.a = 1;
o.b = 2;
o.c = 3;
//o.d = 4; //编译错误
}
}
package ooday05_vis;
import ooday05.Aoo;
public class Coo { //演示同包的
void show(){
Aoo o = new Aoo();
o.a = 1;
//o.b = 2; //编译错误
//o.c = 3; //编译错误
//o.d = 4; //编译错误
}
}
class Doo extends Aoo{ //跨包继承----演示protected
void show(){
a = 1;
b = 2;
//c = 3; //编译错误
//d = 4; //编译错误
}
}
3,final:最终的、不能改变的------------单独应用几率低
修饰变量:变量不能被改变
//演示final修饰变量
class Eoo{
final int a = 5;
void test(){
//a = 55; //编译错误,final的变量不能被改变
}
}
修饰方法:方法不能被重写
//演示final修饰方法
class Foo{
final void show(){}
}
class Goo extends Foo{
//void show(){} //编译错误,final的方法不能被重写
}
修饰类:类不能被继承
//演示final修饰类
final class Hoo{}
//class Ioo extends Hoo{} //编译错误,final的类不能被继承
class Joo{}
final class Koo extends Joo{} //正确,不能当老爸,但能当儿子
4,static:静态的
静态变量:
-
由static修饰
-
属于类,存储在方法区中,只有一份
-
常常通过类名点来访问(也可以用对象名来引用,但是不推荐)
-
何时用:所有对象所共享的数据(图片、音频、视频等)
class Loo{ //演示静态变量
int a;
static int b;
Loo(){
a++;
b++;
}
void show(){
System.out.println("a="+a+",b="+b);
}
}
public class StaticDemo {
public static void main(String[] args) {
Loo o1 = new Loo();
o1.show();
Loo o2 = new Loo();
o2.show();
Loo o3 = new Loo();
o3.show();
System.out.println(Loo.b); //常常通过类名点来访问
}
}
过程: 首先加载类,将类中的静态变量和所有方法放到方法区中,并同时运行静态块。
然后加载loo对象(这时实例变量和静态变量都已经赋默认值),然后调用构造方法。
然后将变量放到栈中,并指向堆中的对象。
最后调用方法区中的show方法给a,b赋值。
静态方法:
-
由static修饰
-
属于类,存储在方法区中,只有一份
-
常常通过类名点来访问(也可以用对象名来引用,但是不推荐)
-
静态方法中没有隐式this传递,所以不能直接访问实例成员
-
何时用:方法的操作与对象无关
class Moo{ //演示静态方法
int a; //实例变量(对象点来访问)
static int b; //静态变量(类名来访问)
void show(){ //有隐式this
System.out.println(this.a);
System.out.println(Moo.b);
}
static void test(){ //没有隐式this
//静态方法中没有隐式this传递,没有this就意味着没有对象
//而实例变量a必须通过对象点来访问,所以如下语句编译错误
//System.out.println(a); //编译错误
System.out.println(Moo.b);
}
}
class Noo{ //演示静态方法何时用
int a; //实例变量(描述对象的属性)
//show方法中访问了对象的属性a,意味着与对象有关,所此不能设计为静态方法
void show(){
System.out.println(a);
}
//plus方法中没有访问对象的属性,意味着与对象无关,所以建议设计为静态方法
static int plus(int num1,int num2){
int num = num1+num2;
return num;
}
}
public class StaticDemo {
public static void main(String[] args) {
Moo.test(); //常常通过类名点来访问
}
}
静态块:
-
由static修饰
-
属于类,在类被加载期间自动执行,一个类只能加载一次,所以静态块也只执行一次
-
何时用:加载/初始化静态资源(图片、音频、视频等)
class Poo{
static { //加载类时自动执行----最早执行
System.out.println("静态块");
}
Poo(){
System.out.println("构造方法");
}
}
public class StaticDemo {
public static void main(String[] args) {
Poo o4 = new Poo();
Poo o5 = new Poo();
Poo o6 = new Poo();
}
}
用构造方法赋值和用静态块赋值的不同:
补充:
1,成员变量分两种:
- 实例变量:没有static修饰,属于对象的,存储在堆中,有几个对象就有几份,通过引用/对象打点来访问
- 静态变量:由static修饰,属于类的,存储在方法区中,只有一份,能过类名打点来访问
2, 内存管理:由JVM来管理的
- 堆:new出来的对象(包括实例变量)
- 栈:局部变量(包括方法参数)
- 方法区:.class字节码文件(包括静态变量、所有方法)
3,
Scanner scan = new Scanner(System.in);
int a = scan.nextInt(); //实例方法
double b = scan.nextDouble(); //实例方法
double c = Math.random(); //静态方法
Arrays.sort(arr); //静态方法
1.常见问题:
1)图片必须放在与src并列关系的img文件夹中,否则读取不到
2)测试的时候一定要保证输出的都是8,因为明天要往窗口上画了
3)如下代码是重载了还是重写了?
class Aoo{
void show(){
}
}
class Boo extends Aoo{ //Boo把Aoo中的show()继承过来了
void show(String name){ //在此处发生了重载
}
}
Boo o = new Boo();
o.show();
o.show("zhangsan");
2.常见面试题:
1)重写与重载的区别:
1.1)重写(override):发生在父子类中,方法名相同,参数列表相同
----当觉得从超类继承过来的方法不好时,所做的修改
1.2)重载(overload):发生在同一类中,方法名相同,参数列表不同
----是完全不同的方法,只是方法名正好相同而已
2)实例变量与静态变量的区别:
2.1)实例变量:
没有static修饰,属于对象,存储在堆中,有几个对象就有几份,由对象点来访问
2.2)静态变量:
由static修饰,属于类,存储在方法区中,只有一份,由类名点来访问
3.代码分析题:-----------Aoo o = new Boo();
//静态块是在加载类的时候自动执行,构造方法是在创建对象时自动执行
//静态块一定先执行超类的,而后再执行派生类的
//构造方法一定先执行超类的,而后再执行派生类的
//输出: 1,3,2,4
class Aoo{
static{
System.out.println(1);
}
Aoo(){
System.out.println(2);
}
}
class Boo extends Aoo{
static{
System.out.println(3);
}
Boo(){
System.out.println(4);
}
}
*/
4,static final常量:应用率高
-
必须声明同时初始化
-
由类名点来访问,不能被改变
-
建议:常量所有字母都大写,多个单词用_分隔
-
编译器在编译时会常量直接替换为具体的数,效率高
-
何时用:数据永远不变,并且经常使用
public class StaticFinalDemo {
public static void main(String[] args) {
System.out.println(Aoo.PI); //通过类名点来访问
//Aoo.PI = 3.1415926; //编译错误,常量不能被改变
//1)加载Boo.class到方法区中
//2)静态变量num一并存储到方法区中
//3)到方法区中获取num的值并输出
System.out.println(Boo.num);
//编译器在编译时会将常量直接替换为具体的值,效率高
//相当于System.out.println(5);
System.out.println(Boo.COUNT);
}
}
class Boo{
public static int num = 5; //静态变量
public static final int COUNT = 5; //常量
}
class Aoo{
public static final double PI = 3.14159;
//public static final int NUM; //编译错误,常量必须声明同时初始化
}
5,抽象方法:
- 由abstract修饰
- 只有方法的定义,没有具体的实现(连{}都没有)
6, 抽象类
-
由abstract修饰
-
包含抽象方法的类必须是抽象类,不包含抽象方法的类也可以声明为抽象类
-
抽象类不能被实例化(new对象)
-
抽象类是需要被继承的,派生类:
- 重写所有抽象方法--------------------变不完整为完整(常用)
- 也声明为抽象类-----------------------不常用
-
抽象类的意义:
-
封装共有的属性和行为-------------------代码复用
-
为所有派生类提供统一的类型----------向上造型(代码复用)
-
可以包含抽象方法,为所有派生类提供了统一的入口(能点出来),
派生类的行为不同,但入口是一致的,同时相当于定义了一个标准
-
7, 设计规则:
-
将派生类所共有的属性和行为,抽到超类中-----------------抽共性
-
派生类的行为都一样,设计为普通方法
派生类的行为都不一样,设计为抽象方法
8, 抽象方法/抽象类的疑问:
-
抽象方法存在的意义是什么?
- 保证当发生向上造型时,通过超类型的引用能点出来那个方法
-
既然意义只在于能点出来,那为什么不设计为普通方法?
-
若设计为普通方法,则派生类可以重写也可以不重写,而设计为抽象方法,可以强制派生类必须重写
------做了个标准,强制必须重写
-