JAVASE 第五式

文章详细阐述了Java编程中的接口、变量和方法的默认属性,类加载顺序,子类与父类的关系,异常处理机制,内存管理,以及垃圾回收算法。还涵盖了多态、反射、泛型、文件操作、流的概念和分类,以及Java内存模型和垃圾收集器的工作原理。
摘要由CSDN通过智能技术生成


接口中的变量默认是public static final 的,方法默认是public abstract 的
-------------

--

非静态内部类可以访问

静态内部类可以访问


new Sub();在创造派生类的过程中首先创建基类对象,然后才能创建派生类。

创建基类即默认调用Base()方法,在方法中调用callName()方法,

由于派生类中存在此方法,则被调用的callName()方法是派生类中的方法,
此时派生类还未构造,所以变量baseName的值为null

类的加载顺序:

1、父类静态代码块(包括静态初始化块,静态属性,但是不包括静态方法)

2、子类静态代码块(包括静态初始化块,静态属性,但是不包括静态方法)
3、父类非静态代码块(包括非静态初始化块,非静态属性)

4、父类的构造函数

5、子类非静态代码块(包括非静态初始化块,非静态属性)

6、子类构造函数

其中:类中静态代码块按照声明顺序执行,并且1和2 不需要调用new类实例的时候就执行了(意思就是在类加
载到方法区的时候就开始执行的)

其次,需要理解子类覆盖父类方法的问题,也就是方法重写与实现多态问题。
Base b = new Sub(); 他为多态的一种表现形式。声明的是Base,实现是Sub类,理解为编译时表现Base类
的特性,运行时表现Sub类的特性

当子类覆盖父类的方法时候,意思是父类的方法已经被重写,题目中父类初始化调用的方法为子类实现的方法
子类实现的方法中调用baseName为子类中的私有属性。

执行到步骤4,子类非静态代码块和初始化步骤还没有到,子类中的baseName还没有初始化,所以此时baseName
为空,结果为NUll

使用反射可以看吃子类是继承了父类的私有方法的(不管是否是final),只是直接调用父类的私有方法不可以。但是利用反射的方式可以调用。

构造器、静态初始化块、实例初始化块不继承

必须实现接口中所有的方法,在实现类中实现接口时,方法的名字、返回值类型、参数的个数以及类型必须与接口中的完全一致,并且必须实现接口中的所有方法

接口实现类相当于子类,子类的访问权限是不能比父类小的

接口中所有方法默认都是public的,如果不是public,那么只能在同个包下被实现,可访问的权限就就降低了很多,那么在实现类中,实现的类相当于子类。子类的访问权限是不能比父类小的,而在java中一个类如果没有权限的修饰符,默认是friendly(同一个包内的其他类才可以访问),所以在实现类中一定要写public


由于arr[0] =0,所以在进入 test()方法里面会在第一个if 上抛出一个 NullPointerException,接着会执行 finally 的语句, (finally语句先于 return 和 throw语句执行),输出一个'e,然后回到 main方法中,由于捕捉到异常,所以进入到catch语句中,然后打印一个'E',所以最终结果为"eE"


一个 .java文件中,可以有多个类,包括内部类和外部类。考虑到内部类的原因,一个 .java文件中了可以有多个public类。

但是对于外部类而言,一个 .java文件必须只能有一个public类,同时这个类的类名必须和 .java的文件名保持一致(包括大小写)


forward,服务器获取跳转页面内容传给用户,用户地址栏不变 (一次请求)

redirect,服务器向用户发送转向的地址,redirect后地址栏变成新的地址 (本质上 两次请求)



在Java中,变量有两种类型,一种是原始类型,一种是引用类型。

原始类型一共有8种,它们分别是char,boolean,byte,short,int,long,float,double。在Java API中,
有它们对应的包装类,分别是(首字母大写)
Character,Boolean,Byte,Short,Integer,Long,Float,Double(char,int的变化稍微大点)。

JAVA JVM对于不同的原始类型会分配不同的存储空间,具体分配如下:

byte  : 1个字节    8位
最大值: 127   (有符号)

short : 2个字节    16位                            32767

int :     4个字节    32位                            2147483647

long:   8个字节    64位                            9223372036854775807

float:   4个字节    32位                            3.4028235E38

double:8个字节   64位                            1.7976931348623157E308

枚举(enum)类型是Java 5新增的特性,它是一种新的类型,允许用常量来表示特定的数据片断,而且全部
都以类型安全的形式来表示,是特殊的类,可以拥有成员变量和方法。

java是自动管理内存的,通常情况下程序运行到稳定状态,内存大小也可以达到哟i个基本稳定的值,但是内存谢泄露导致GC不能回收泄露的垃圾,内存不断变大,最终超出了内存界限,抛出OutOfMemoryException;


System是java.lang中的类,out为System中的一个静态成员变量,这个变量是一个java.io.PrintStream类的对象,println()是java.io.PrintStream类的方法,所有可以调用类.静态方法.println()方法


一句话解决:string是值传递,stringbuffer是引用传递。


java中为单继承,但是可以实现多个接口



flush()函数强制将缓存区中的字符流,字节流等输出,目的是如果输出流输出到缓冲区完成后,缓冲区并没有填满。那么缓冲区将会一致等待被填满。所以在关闭输出流之前按要调用flush.


a++,a--是表达式要进行赋值的

a++ 先把10赋值给a  在加一,所以左边是10,     但此时a=11。
a-- 也是先赋值a=11,在减一, 所以 10+11 = 21  但此时a=10

导入 java.util.*不能读取其子目录的类,

因为如果java.uti里面有个a类,java.util.regex里面也有个a类,我们若要是去调用a类的方法或者属性时候,应该使用哪个a类呢
----

floor: 求小于参数的最大整数。返回double类型-----n. 地板,地面
         例如:Math.floor(-4.2) = -5.0
-----------------------------------------------------------
ceil:   求大于参数的最小整数。返回double类型-----vt. 装天花板;
         例如:Math.ceil(5.6) = 6.0
-----------------------------------------------------------
round: 对小数进行四舍五入后的结果。返回int类型
         例如:Math.round(-4.6) = -5

Servlet过滤器的配置包括两个部分:

第一部分是过滤器在Web应用中的定义,由<filter>元素表示。包括<filter-name>和<filter-class>两个必需的子元素

第二部分是过滤器映射的定义,由<filter-mapping>元素表示。可以将一个过滤器映射到一个或者多个Servlet或者JSP文件,也可以采用url-pattern将过滤器映射到任意特征的URL。




按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。

节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。
如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,
称为流的链接。

JAVA常用的节点流:

文 件  FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流。
字符串 StringReader StringWriter 对字符串进行处理的节点流。
数 组  ByteArrayInputStream 
ByteArrayOutputStreamCharArrayReader CharArrayWriter 对数组进行处理的节点流
(对应的不再是文件,而是内存中的一个数组)。
管 道  PipedInputStream PipedOutputStream PipedReaderPipedWriter对管道进行处理的节点流。
常用处理流(关闭处理流使用关闭里面的节点流)

缓冲流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter  
增加缓冲功能,避免频繁读写硬盘。

转换流:InputStreamReader OutputStreamReader 实现字节流和字符流之间的转换。
数据流 DataInputStream DataOutputStream  等-提供将基础数据类型写入到文件中,或者读取出来.
流的关闭顺序
一般情况下是:先打开的后关闭,后打开的先关闭
另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b。例如,处理流a依赖节点流b,
应该先关闭处理流a,再关闭节点流b
可以只关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法。

两个最基本的java回收算法:复制算法和标记清理算法

复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
标记清理:一块区域,标记可达对象(可达性分析),然后回收不可达对象,会出现碎片,那么引出
标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象

两个概念:新生代和年老代
新生代:初始对象,生命周期短的
永久代:长时间存在的对象
整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理
CMS收集器,基于标记清理
G1收集器:整体上是基于标记 整理 ,局部采用复制

综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。


没有break会导致出现 穿透现象。

当i=2时,执行程序

Case2:result=4;
Case3:result=4+6=10;

没有Break,就会顺序执行下去

因为byte是有符号单字节整形,所以存储数字范围是[-128~127]
而127[01111111]+1==128[10000000]。

为什么呢?
因为科学家定义数字的时候是一个环,最大的数字后面就是最小,这样才可以把[0·255]分配给[-128·127]。
底层就是补码的概念。

好,我们再从java程序上运行一次
public class HelloWorld {
    public static void main(String []args) {
       byte b = (byte)129;
       byte c = (byte)128;
       System.out.println(b);
       System.out.println(c);
    }
}


-------

(1)is-a:继承关系;比如羊和绵羊;这种事物(绵羊)是那种事物(羊)中的一个种类;如果一个类继承了另外一个类,这两个类的关系是is-a的关系

(2)has-a:从属 关系;比如羊和羊身上的羊毛;这种事物(羊毛)隶属于那种事物(绵羊),是它的一个部分、部件。如果一个类实现了一个接口类,这个类必须实现接口类的所有方法。这两个类的关系是has-a的关系。

(3)is-like-a:组合关系:这个和is-a的区别是:A类继承了B类,如果A类只有B类方法,那么就是is-a;如果在is-a的基础上,A类还添加了自己的方法,那么就是is-like-a;


下面的方法可用在 Servlet 程序中读取 HTTP 头。这些方法通过 HttpServletRequest 对象可用:

1)Cookie[] getCookies()
返回一个数组,包含客户端发送该请求的所有的 Cookie 对象。

2)Object getAttribute(String name)
以对象形式返回已命名属性的值,如果没有给定名称的属性存在,则返回 null。

3)String getHeader(String name)
以字符串形式返回指定的请求头的值。Cookie也是头的一种;

4)String getParameter(String name)
以字符串形式返回请求参数的值,或者如果参数不存在则返回 null。

ServerSocket(int port) 是服务端绑定port端口调accept()监听等待客户端连接它返回一个连接队列中的一个socket

Socket(InetAddress address ,int port) 是创建客户端连接主机的socket流,其中InetAddress是用来记录主机的类

port指定端口。

socket和servletSocket的交互如下图所示


default和protected的区别是:
前者只要是外部包,就不允许访问。
后者只要是子类就允许访问,即使子类位于外部包。

总结:default拒绝一切包外访问;protected接受包外的子类访问

编译看左边,运行看右边。也就是是编译的时候会把它当成左边的类型,运行的时候看右边类型的方法体。这个题动物类没有另一个方法,而b调用了,所以编译器会认为b是一个动物类,所以报错。这就是多态的特性


final类型的变量一定要初始化,因为final的变量不可更改。


A.子进程得到的是除了代码段是与父进程共享以外,其他所有的都是得到父进程的一个副本,子进程的所有资源都继承父进程,得到父进程资源的副本,子进程可获得父进程的所有堆和栈的数据,但二者并不共享地址空间。两个是单独的进程,继承了以后二者就没有什么关联了,子进程单独运行;进程的线程之间共享由进程获得的资源,但线程拥有属于自己的一小部分资源,就是栈空间,保存其运行状态和局部自动变量的。

B.线程之间共享进程获得的数据资源,所以开销小,但不利于资源的管理和保护;

而进程执行开销大,但是能够很好的进行资源管理和保护。

C.线程的通信速度更快,切换更快,因为他们共享同一进程的地址空间。

D.一个进程可以有多个线程,线程是进程的一个实体,是CPU调度的基本单位。



1、创建泛型对象的时候,一定要指出类型变量T的具体类型。争取让编译器检查出错误,而不是留给JVM运行的时候抛出类不匹配的异常。

2、JVM如何理解泛型概念 —— 类型擦除。事实上,JVM并不知道泛型,所有的泛型在编译阶段就已经被处理成了普通类和方法。 处理方法很简单,我们叫做类型变量T的擦除(erased) 。

总结:泛型代码与JVM

① 虚拟机中没有泛型,只有普通类和方法。

② 在编译阶段,所有泛型类的类型参数都会被Object或者它们的限定边界来替换。(类型擦除)

③ 在继承泛型类型的时候,桥方法的合成是为了避免类型变量擦除所带来的多态灾难。 无论我们如何定义一个泛型类型,相应的都会有一个原始类型被自动提供。原始类型的名字就是擦除类型参数的泛型类型的名字。



静态块:用static申明,JVM加载类时执行,仅执行一次
构造块:类中直接用{}定义,每一次创建对象时执行
执行顺序优先级:静态块>main()>构造块>构造方法 、静态块按照申明顺序执行,

先执行Test t1 = new Test();
所有先输出blockA,然后执行静态块,输出blockB,最后执行main
方法中的Test t2 = new Test();输出blockA


Iterator支持从原籍和中安全地删除对象,只需要在Iterator上调用 remove()即可。

这样做的好处是可以避免ConcurrentModifiedException,当打开Iterator迭代集合时,同时又在对集合进行修海,有些集合不允许在迭代时删除或添加元素,但调用Iterator的 remove()方法是个安全的做法



JAVA 序列化 :保存(持久化)对象及其状态到内存或者磁盘
使用 Java 对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的”状态”,即它的成员变量。由此可知,对象序列化不会关注类中的静态变量

补充:

Transient 关键字阻止该变量被序列化到文件中
1. 在变量声明前加上 Transient 关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。


2. 服务器端给客户端发送序列化对象数据,对象中有一些数据是敏感的,比如密码字符串等,希望对
该密码字段在序列化时,进行加密,而客户端如果拥有解密的密钥,只有在客户端进行反序列化
时,才可以对密码进行读取,这样可以一定程度保证序列化对象的数据安全

序列化的是对象,不是类,类变量不会被序列化



Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。

Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。

新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
堆的内存模型大致为:
 



从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。
本人使用的是 JDK1.6,以下涉及的 JVM 默认值均以该版本为准。
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。
老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。
默认的,Edem : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。
JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。
因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间


File类能操作文件本身,但是不能对文件的内容做修改,能够读写文件的不是file,是数据流(outputStream and InputStream)


运行异常,可通过java虚拟机来自行处理,非运行异常,我们应该捕获或者抛出

java异常都继承自类Throwable,Throwable子类有Error和Exception,其中Exception又分为运行时异常和编译时异常了。编译时异常时未雨绸缪性质的异常,是防范,需要显示处理,运行时异常时程序员问题造成的,并不需要强制进行显示处理

运行时异常: 都是RuntimeException类及其子类异常,
如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,
这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,
程序应该从逻辑角度尽可能避免这类异常的发生。
       
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,
即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

非运行时异常 (编译异常): 是RuntimeException以外的异常,类型上都属于Exception类及其子类。
从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。
如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值