Java学习笔记6

 
======================================================================
Java  
6 :  Java 高级特性
修饰符 ; 接口 , 内部类 , 对象 , 包装类 , 集合 , 异常处理 , 反射 .
======================================================================
(1)
修饰符。
private,default,protected,public //
不能修饰局部变量
private,default,protected,public:
都能修饰属性和方法 ,
但是只有 default,public 能修饰类 .
表1: 类,方法,成员变量和局部变量的可用修饰符
   修饰符   
         
成员方法
构造方法
成员变量
局部变量
abstract
static
public
protected
private
synchronized
native
transient( 暂时的 )
volatile( 易失的 )
final
 
  2 : 访问的级别和可访问范围
访问级别
访问控制修饰参数
同类
同包
子类
不同的包
公开
Public
受保护
Protected
默认
Default( 没有修饰 )
私有
private

(2) static //
静态的 .  
能修饰属性 , 方法 , 初始代码块 .
package test;
public class TestStatic {
public static void main(String[] args){
       MyClass mc1= new MyClass();
       MyClass mc2= new MyClass();
       mc1. a =10;
       System. out .print( "mc1.a=" +mc1. a );
       System. out .print( "mc2.a=" +mc2. a );
       mc2. a =20;
       System. out .print( "mc1.a=" +mc1. a );
       System. out .print( "mc2.a=" +mc2. a );
       System. out .print( "MyClass.a=" +MyClass. a ); // 因为 a 是类变量 , 所以可以用类名调用 .
       System. out .println(); // out System 里的公有的属性 .
              MyClass.m1(); // 类名调用 .
       }
}
class MyClass{
       static int a =1; // 此时叫类变量 , 全类公有 . 因此可以用类名调用 .
       int b =2; // 创建对象的时候才分配空间 , 初始化 .
       public static void m1(){
              System. out .println( a );
              System. out .println( b ); // 静态方法不能访问非静态属性。
       }
       public static void m2(){ // 相当于全类的 , 因此能用类名调用 . 是打破面向对象思想的 .
              System. out .println( a );
              System. out .println( b ); // 编译错误 , 静态方法不能访问非静态属性 . 因为 ,
       }
}
属性 : 类变量 (static), 实例变量 .
局部变量不是属性 .
(4)
静态方法是否能覆盖 ?
静态方法可以覆盖 , 但是必需是静态方法覆盖静态方法 , 非静态方法不能覆盖静态方法 .( 此时就没有了多态 .)
package test;
class TestOverride{
       public static void main(String[] args){
       Super s= new Sub(); // 只有非静态方法的覆盖才有多态 .
       System. out .println(s. a ); // =10
       }
}
class Super{
       static int a =10;
}
class Sub extends Super{
       static int a =20;
}
(5)
静态属性是在什么时候 , 被初始化的 ???
: 在类加载的时候被初始化的 .
(7)
什么叫类加载 ??
: 类加载一次 , 然后就创建静态变量 .( 也就是只创建一次 ). 如果创建对象就不用再次的加载类 , 在然后就创建对象 . 一个类在编译之后会形成 .class 文件 , 存储了类的全部消息 . JVM 第一次需要用到这个类的时候 , 会根据 ClassPath 找到这个 .class 文件 , 用输入流把文件中的消息读入 JVM 并保存起来 , 这样 ,JVM " 认识 " 了这个类 .
类加载时机 : 第一次用这个类的时候 .
1.
第一次创建类的对象 , 会加载
2.
访问类的静态成员 , 会加载 .
3.
声明类的引用 , 不会加载 .
4.
加载子类 , 必然先加载父类
5.
如果调用的是子类从父类中继承到静态方法 , 只会加载父类 .
6.
如果访问的是类的静态常量 , 如果在编译的时候能确定这个常量的值 , 则运行时不会加载 , 否则 , 编译是无法确定常量的值 , 那么运行是就会加载 .
(8)
主方法为什么是静态方法 ?
: 如果不是静态的 . 必需先创建类对象 , 但是此时创建对象的方法是 main 方法里面 , 这样会造成矛盾 . 也就是不能创建对象 . 要解决这个问题就要把 main 方法写成静态的 , 要让 main 方法在创建对象之前调用 ( 因为静态方法和属性是在类加载的时候就调用的 , 因此可以解决这个问题 , 呵呵 )
(9)static
的第三种用法 .( 温馨提示 :static 的前三种用法是 :1. 修饰属性 ,2. 方法 ,3. 初始化代码块 )
//
此时而初始化代码块只能用 static 修饰 , 嘻嘻记住吧 !!!
在第三步 : 调用初始代码块 : 在构造方法前面运行,在初始化属性的时候运行。
在前面加 static 静态初始代码快 . 在类加载的时候运行 , 创建对象的时候不运行这个代码块 .// 太有用了 !! 呵呵 .
重要用处 : 监控虚拟机的类加载 .
1.
创建对象的时候会出现 .
2.
第一次访问静态方法 , 属性 .
3.
声明一个类的一个引用 , 不会加载类 . 虚拟机有延迟加载的功能 ,( 能不加载就不加载 , 也就是编译器能确定的事情 [ 也就是不变的量 ,final 修饰 ], 就不会加载类 , 这样会浪费内存 )
4.
加载子类的时候会加载父类么 ????
: 不单要加载父类而且会先加载父类 .
例子 : 看老师的代码 : TestClassLoad.java
5.
如果你调用从父类继承到的静态方法 , 只加载父类不加载子类 .
例子 : 例子 : 看老师的代码 : TestClassLoad.java
如果覆盖了父类的静态方法 , 就还要加载子类 .
5 个特性都在下面的代码中 :
package test;
public class TestClassLoad{
       public static void main(String[] args){
//   Student s=new Student();
//   Student.m();
//   Student s=null;
//   Sub s=new Sub();
//   Sub.m();
//   System.out.println(ClassA.A);// 这个就不会调入虚拟机 .( 编译器当时就确定了这个数 , 因此就没有必要加载这个类 , 会省下内存空间 , 呵呵 )
       System. out .println(ClassA. B ); // 此时会加载类 . 因为 Math.random(); 的值不确定 , 要进入类才能知道 .
       }
       }
       class Student{
       static { // 修饰的初始化代码块 .[ 温馨提示 : 此时只能用 static 修饰 , 不能用 private,protect,public 修饰 , 嘻嘻 ]
       System. out .println( "Load Student" );
       }
       static int a ;
       public static void m(){}
       public Student(){}
       }
       class Super{ // 验证 [ 加载子类的时候会加载父类么 ]
       static {
       System. out .println( "Load Super" );
       }
       public static void m(){}
       }
       class Sub extends Super{
       static {
       System. out .println( "Load Sub" );
       }
       }
       class ClassA{ // 验证编译器确定了变量的值 , 就不会加载类
       static {
       System. out .println( "Load ClassA" );
       }
       public static final int A =2*5; // 确定不会变的量 .
       public static final double B =Math.random(); // 只有调入这个类才能确定的量 .
}
(10) 和静态有关的模式模式: GOF green of four; 23种模式
1.单例模式: (yi) 一个类只允许他有一个对象.怎么实现??
就要用到单例模式.
具体例子: 这样一个类才只能有一个对象. 实现了这个需求.呵呵.
package test;
 
public class TestClassLoad{
       public static void main(String[] args){
       LaoGong lg1=LaoGong.newInstance();
       LaoGong lg2=LaoGong.newInstance();
       LaoGong lg3= new LaoGong(); // 这个会出现编译错误 , 把无参的构造方法变成私有。
       LaoGong lg4=LaoGong.newInstance(); // 只有这样才能编译通过 .
       System. out .println( "" );
       }
}
class LaoGong{
       private static LaoGong lg = new LaoGong(); // 单例模式 ;
       public static LaoGong newInstance(){ // 返回申请的同一个对象。 lg;
              return lg ;
       }
       private LaoGong(){} // LaoGong lg=new LaoGong() 路给堵上 .
}
虚拟机机制: 一般来说一个类只加载一次.
java 起动一个虚拟机.
(11) 如果设计一个方法, 不需要对象. 就用static 修饰. 一般用于JDK 的工具类的。
(12) final
修饰变量.3 个变量都能修饰 , 还能修饰类.
//对于类常量,初始化或者静态初始化代码块中可以赋值.

1. final 修饰变量
这个变量就变成了常量(一旦赋值,以后就不能改变了)//和conste一样,来定义常量.final修饰的变量有两次赋值的机会:申请变量的时候,在构造函数中。
package test;
public class TestFinal {
       public static void main(String[] args) {
              ClassA cs = new ClassA();
              System. out .println(cs.B); // 这样会编译错误 . 没有初始化 , 因为 final 要进行初始化。
              cs.B = 10; // 无法为最终变量 B 指定值 . 因此要在创建对象时赋值。 .
       }
}
class ClassA {
       final int B; // 如果 , 加了 final 默认值无效 . 因为是常量所以要是大写 .
       final int B = 10; // 第一种赋值的方法 .
       public ClassA(){}
       public ClassA( int b) { // 第二种赋值方法 .
              this .B = B;
       }
       public void m() {
              int a = 10;
              a = 20;
       }
}
2. final 修饰类和方法 .
例子: 修饰类,则这个类没有子类,如果一个类用final修饰,那么这个类不能被继承.
final class Super{ // 编译错误 , 无法从最终类继承 . 例子 : String 类是一个 final .
public final void m(){} // 如果一个类用 final 修饰 , 那么这个类不能被继承 .
}
//final 的用处 : 自己写的方法 , 不希望被子类修改 , 保持了方法的稳定性 .
class Sub extends Super{
public void m(){} // 编译错误 . 无法覆盖因为被覆盖的方法是 final.
}
// 判断 : 一个 final 类的其中所有的方法全是 final ????? 对了 , 呵呵 .
public static final double A=3.14//公开静态常量.
======================================================================
package test;
public class TestFinal {
       public static void main(String[] args) {
              ClassA cs = new ClassA();
              System. out .println(cs. A ); // 编译器在编译的时候 System.out.println(10);10
                                                               // 是静态常量 . 因此不会加载 ClassA();
              System. out .println(cs. B ); // 编译器在编译的时候不能确定 B 的值 , 因此会加载 ClassA();
       }
}
class ClassA {
       static {
              System. out . println ( "Load ClassA" );
       }
       public static final int A = 2 * 5; // 编译器能确定,因此就不装载子类了。
       public static final double B = Math.random(); // 编译器不能确定此时的值,因此要装载子类。
}
======================================================================
(14) abstract 表示抽象的 修饰类, 方法,抽象类:用来被继承.
抽象方法:只有定义没有实现.如果一个类里边有抽象方法,这个类必需是抽象类.一个抽象类,并不一定有抽象方法.
抽象类有构造方法
通过abstract,我们可以把一个方法定义
例子:
package test;
public class TestAbstact{
       public static void main(String[] args){
       Super s= new Super(); // 是抽象的不能去创建对象 , 因此不能作为运行时类型 .
       Super s; // 可以声明引用 . 他是用来被继承的 .
       Super s= new Sub(); // 可以 , 抽象类可以作为一个类的半成品 .( 抽象类作为编译时类型 , 子类作为运行时类型 .)
       s.m(); // 找子类中实现的方法 .
       }
       }
abstract class Super{
       public abstract void m(); // 抽象方法 , 只有声明没有实现 .
       }
class Sub extends Super{ // 如果不实现他 , 就不会编译通过 , 嘻嘻 , 必需全部实现父类的抽象方法 .
       public void m(){
       System. out .println( "hehe" ); // 实现了父类的这个方法 . 呵呵 .
       }
}
final abstract 都不能修饰构造方法.
======================================================
(14) 修饰符的组合方式;final abstract 都不能修饰构造方法.
抽象类,可以有构造方法,是让子类调用的.
但是,接口没有构造方法.
private ,static,final 可以任意的组合,去修饰一个方法.
三个任意一个都不能和abstract 和用在一起.
private
static          
不能混用         abstract
final

---------------------------------------------
抽象方法的作用:
======================================================================
(15) 接口语法:
1. 一个接口就是一个抽象类,而且是一个特殊的抽象类,所有属性默认都是公开静态常量,所有的方法默认都是公开抽象方法.接口之间可以多继承.一个类在继承另外一个类的同时,还可以实现多个接口,
2. 一个类实现一个接口,如果这个类不是抽象类的化,那么就一定要实现接口中定义的方法.
3. 接口没有构造方法.
例子:
package test;
public class TestInterface{
       public static void main(String[] args){
       Impl i= new Impl();
       MyClass mc=i;
       mc.m6(); // 只能调用 m6();
       IA ia=i;ia.m1();ia.m2();
       IB ib=i;ib.m3();
       IC ic=i;ic.m1();ic.m2();ic.m3();ic.m4();
       ID id=i;is.m5();
       }
}
abstract class AbstractClass { // 接口是特殊的抽象类
       public abstract void m1();
}
class Sub extends Super{
       public static final int A =10;
       public abstract void m1();
       public abstract void m2();
}
interface IA{ // 此接口和上一个抽象类在逻辑上是完全等价的 .
       int a =10; // 接口的属性 . 接口中属性公开静态常量 .
// 接口中没有构造方法 .
       void m1(); // 接口中所有的方法都是公开抽象方法 .
       void m2();
}
interface IB{ //
       void m3();
}
interface IC extends IA,IB{ // 接口能够继承 . 而且能够多继承 .
       void m4();
}
interface ID{ //
       void m5(); //
}
class Impl extends IA{ // 错误 , 类和类之间有继承 , 接口和接口之间有继承 , 类和接口之间只有实现 .
}
class Impl implements IA{ // 实现接口也要实现里面的抽象方法 .
       void m1(){} // 编译不通过
       public void m1(){} // 这样才能编译通过 , 嘻嘻 .
       public void m2(){} // 这样才能编译通过 , 嘻嘻 .
       }
abstract class MyClass{
       public void m6() {
       }
}
class Impl extends MyClass implements IC,ID{ // 这样会绕过单继承的限制 , 而且可以继承多个接口 .
       public void m1(){} public void m2(){} public void m3(){} public void m4(){} public void m5(){}
       public void m6(){}
}
class Sub extends Super{
       public abstract void m1(); public abstract void m2();
}
class Super{
      
}
======================================================================
以下是老师的笔记:
static
属性 类变量 全类共有 类加载时创建,类名访问
 方法 类名调用,静态方法中不能访问类的非静态成员,可以覆盖,只能被静态方法覆盖,没有多态
 初始代码块 类加载时运行
 类加载:
 一个类编译之后会形成.class文件,储存了类的全部信息。当JVM第一次需要用到这个类的时候,会根据ClassPath找到这个.class文件,用输入流把文件中的信息读入JVM并保存起来,这样,JVM就“认识”了这个类
 类加载时机:第一次用这个类的时候
 1. 第一次创建类的对象,会加载
 2. 访问类的静态成员,会加载
 3. 声明类的引用,不会加载
 4. 加载子类,必然先加载父类
 5. 如果调用的是子类从父类中继承到的静态方法,只会加载父类
 6. 如果访问的是类的静态常量,如果在编译的时候能够确定这个常量的值,则运行时不会加载,否则,编译时无法确定常量值,那么运行时就会加载
 设计模式:单例模式
 用途:一个类只能有一个对象
 实现:会有一个静态的属性,就是该类的一个对象。提供一个静态方法,来获得这个唯一的静态属性(单例),同时构造方法私有    
final
 变量:常量,一旦赋值,不能改变,为属性常量赋值的时机:对于实例常量,初始化或者构造方法中可以赋值;对于类常量,初始化或者静态初始代码块中可以赋值
 方法:不能被覆盖
 类 :不能被继承
abstract
 方法:只有定义,没有实现
 类:不能构造对象,但可以用来声明一个引用(作为编译时类型)
 如果一个类有抽象方法,这个类必须是抽象类,如果一个类是抽象类,不一定有抽象方法
 子类继承一个抽象类,就必须覆盖(实现)父类(抽象类)中的所有抽象方法,否则,子类就也得是抽象类
 抽象类有构造方法
 通过abstract,我们可以把一个方法的定义放在父类,而留给子类实现。
接口
 一个接口是一个特殊的抽象类。所有的属性默认都是公开静态常量,所有的方法默认都是公开抽象方法
 接口之间可以多继承
 一个类在继承另外一个类的同时,还可以实现多个接口。而实现的每一个接口都将成为这个类的兼容类型,允许多态的使用
 一个类实现一个接口,如果这个类不是抽象类的话,那么就一定要实现接口中定义的所有方法
 接口没有构造方法
 接口的作用:
 1.实现多继承
   区分主类型和次要类型,接口的引入就使得我们可以对事物的共性作一个再抽象,抽象出副类型。
   这种多继承的关系不会破坏类之间单继承树状关系的复杂度
 2.标准
 标准的制定者、实现者、使用者分离
 解耦合的工具
 标准的使用者和标准的实现者通过接口实现弱耦合
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炼丹狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值