abstract和interface分别定义抽象类和接口。抽象类主要作为多个类的模板,接口定义了多类应该遵守的规范。
Integer inObj = 5;//基本类型变量赋给Integer对象
object boolObj = ture;
int it = inObj;//Integer对象赋给int类型变量
String intStr = "123";//将字符串“123”转换成int变量
int it1 = Integer.parseInt(intStr);
int it2 = Integer.valueOf(intStr);
//把float变量转换成String变量
String ftStr = String.valueOf(2.345f);
String intStr = 5 + "";//int变量转换为String变量
static修饰的成员就是类成员,包括类变量、类方法、静态初始化块。
class Singleton {
private static Singleton instance;//使用类变量缓存曾创建的实例
private Singleton(){};//对构造器隐藏
private static Singleton getInstance(){//静态方法,返回Singleton实例
if(instance == null)
instance = new Singleton();//创建一个对象,并缓存
return instance;
}
}
public class SingletonTest{
public static void main(Sitng[] args){
Singleton s1 = Singleton.getInstance();//创建Singleton对象不能通过构造器
Singleton s2 = Singleton.getInstance();//只能通过getInstance方法得到实例
System.out.println(s1 == s2);//输出true
}
}
public class StringJoinTest{
public static void main(String[] args){
String s1 = "疯狂java";
String s2 = "疯狂" + "java";
System.out.println(s1 == s2);//true
String c1 = "疯狂java";
String c2 = "java";
String c3 = c1 + c2;
System.out.println(c1 == c3);//flase
}
}
编译器在编译阶段就确定s2为“疯狂java”,系统会让s2直接指向常量池中的缓存的“疯狂java”字符串,因此s1 == s2;对c3,值是由c1c2连接运算后得到的,c1c2只是普通变量,编译时不会执行“宏替换”,因此编译器无法在编译时确定c3 的值,c3无法指向“疯狂java”字符串,所以false;(将c1c2使用final修饰,输出true)。
//定义一个抽象类
public abstract class Shape{
private String color;
//定义一个计算周长的抽象方法
public abstract double calPerimeter();
...
}
//定义Triangle类继承Shape抽象类
public class Triangle extends Shape{
private double a,b,c;
//重写Shape类的计算周长的抽象方法
public double calPerimeter(){
return a+b+c;
}
}
将这种抽象进行得更彻底,则可以提炼出一种更加特殊的“抽象类”——接口(interface)
interface InterfaceC extends InterfaceA, InterfaceB{...}
[修饰符] class 类名 extends 父类 implements 接口1,接口2..{
...
}
public class StaticInnerClassTest{
private int propl = 5;
private static int prop2 = 9;
static class StaticInnerClass{
//静态内部类里可以包含静态成员
private static int age;
public void accessOuterProp(){
//静态内部类无法访问外部类的**实例变量**
System.out.println(propl);//×
//静态内部类访问外部类的**静态成员**
System.out.println(prop2);//√
}
}
}
public class AccessStaticInnerClass{
static calss StaticInnerClass{
private static int prop1 = 5;
private int prop2 = 9;
}
public void accessInnerProp(){
System.out.println(propl);//×
//通过**类名**访问静态内部类的类成员
System.out.println(StaticInnerClass.propl);//√
System.out.println(prop2);//×
//通过**实例**访问静态内部类的实例成员
System.out.println(new StaticInnerClass().propl);//√
}
}
OuterClass.InnerClass varName
OuterINstance.new InConstructor()
class Out{
class In{//内部类
public In(String msg){
System.out.println(msg);
}
}
}
public class CreateInnerInstance{
public static void main(String[] args){
Out.In in = new Out().new In("测试信息");
//上面代码等同于下面三句代码
Out.In in ;//使用OutterClass.InnerClass形式定义内部类变量
Out out = new Out();//创建外部类实例,非静态内部类实例将寄生在该实例中
//通过**外部类实例**和**new**来调用内部类**构造器**创建非静态内部类实例
in = out.new In("测试信息");
}
}
public class SubClass extends Out.In{
//显示定义SubClass的构造器
public SubClass(Out out){
//通过传入的Out对象显示调用In的构造器
out.super("hello");
}
}
非静态内部类In类的构造器必须使用外部对象来调用,代码中super代表调用In类的构造器,out代表外部类对象。
new OuterClass.InnerConstructor()
class StaticOut{
//定义一个静态内部类
static class StaticIn{
public StaticIn(){]
System.out.println("静态内部类的构造器");
}
}
}
public class CreateStaticInnerInstance{
public static void main(Sting[] args){
StaticOut.StaticIn in = new StaticOut.StaticIn();
//上面代码等于下面两行代码
StaticOut.StaticIn in;//使用OuterClass.InnerClass的形式定义内部类变量
in = new StaticOut.StaticIn();//通过new来调用内部类构造器创建静态内部类实例
}
}
//定义一个Product接口
interface Product{
public double getPrice();
public string getName();
}
public class AnonymosTest{
public void test(Product p){
System.out.println("买了" + p.getName() + "花了" + p.getPrice());
}
public static void main(String[] args){
AnonymousTest ta = new AnonymousTest();
//调用test方法时,需传入一个Product参数,此处传入**匿名实现类的实例**
ta.test( new Product(){
public double getPrice(){
return 567.8;
}
public String getName(){
return "AGP显卡";
}
} );
}
}
上面程序中的test()方法需要一个Product对象作为参数,但Product只是一个接口,无法直接创建对象,因此考虑创建一个Product接口实现类的对象传入该方法:如果Product接口实现类需要重复,将该类定义成一个独立类;如果Product接口实现类只需一次使用,定义一个匿名内部类。
Lambda表达式支持将代码块作为方法参数,允许使用更简洁的代码来创建只有一个抽象方法的接口(被称为函数式接口)的实例。
pa.process(target, new Command(){
public void process(int[] target){
int sum = 0;
System.out.println(sum);
}
});
//下式一样,**Lambda表达式**
pa.process(array, (int[] target) -> {
int sum = 0;
System.out.println(sum);
});
Runnable r = () ->{
for(int i = 0 ; i < 100; i++)
System.out.println();
}
//强制类型转换
Object obj = (Runnable)() -> {
for(int i = 0 ; i < 100; i++)
System.out.println();
}
//函数式接口
interface Converter{
Integer convert(String from);
}
//使用Lambda表达式创建一个Converter对象
Converter converter1 = from -> Interger.valueOf(from);
//调用converter1对象的convert()方法将字符串转换为整数
Integer val = converter1.convert("99");
//**等于上面两句**
//方法引用代替Lambda表达式:**引用类方法**
//函数式接口中被实现方法的全部参数传给该**类方法**作为参数
Converter converter1 = Integer :: valueOf;
//使用Lambda表达式创建一个Converter对象
Converter converter2 = from -> "fkit.org".indexOf(from);
//调用converter1对象的convert()方法将字符串转换为整数
Integer value = converter2.convert("it");
//**等于上面两句**
//方法引用代替Lambda表达式:**引用特定对象的实例方法**
//函数式接口中被实现方法的全部参数传给该**方法**作为参数
Converter converter2 = "fikt.org" :: valueOf;
//函数式接口
interface MyTest{
String test(String a, int b, int c);
}
//使用Lambda表达式创建一个MyTest对象
MyTest mt = (a, b, c) -> a.substring(b, c);
//调用mt对象的test()方法
String str = mt.test("java i love you", 2, 9);
//**等于上面两句**
//方法引用代替Lambda表达式:**引用某类对象的实例方法**
//函数式接口中被实现方法的**第一个参数**作为调用者,后面参数全部传给该方法作为参数
MyTest mt = Strign :: substring;
//函数式接口
interface YourTest{
JFrame win(String title)
}
//使用Lambda表达式创建一个YourTest对象
YourTest yt = (String a) -> JFrame(a);
//调用yt对象的win()方法
JFrame jf = yt.win("我的窗口");
//**等于上面两句**
//方法引用代替Lambda表达式:**引用构造器**
//函数式接口中被实现方法的全部参数传给该**构造器**作为参数
YourTest yt = JFrame :: new;
Arrays类的有些方法需要Comparator、XXXOperator、XXXFunction等接口的实例,都是函数式接口,因此可以使用Lambda表达式来调用Arrays的类方法。
枚举类也是一种类,只是它比较特殊的类
public enum Gender{
MALE,FMALE;
public String name;//public修饰的实例变量
}
public class GenderTest{
public static void main (String[] args){
//通过Enum的valueOf()方法获取指定枚举类的值
Gender g = Enum.valueOf(Gendder.class, "FEMALE");
//直接为枚举值的name实例变量赋值
g.name = "女";
//直接访问枚举值的name实例变量
System.out.println(g + "代表" + g.name);
}
}
public enum Gender{
//此处的枚举值必须调用对应的构造器来创建
MALE("男"),FEMALE("女");
pivate final String name;
//枚举类的构造器只能使用private修饰
private Gender(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
MALE("男");//等同于下面语句
public static final Gender MALE = new Gender("男");
public interface GenderDesc{
void info();
}
public enum Gender implements GenderDesc{
...
public void info(){
...//实现GenderDesc接口必须实现的方法
}
}
public enum Operation{
PLUS{
public double eval(double x, double y){
return x + y;
}
},
MINUS{
public double eval(double x, double y){
return x - y;
}
};
//为枚举类定义一个抽象方法
//这个抽象方法由不同的枚举值提供不同的实现
public abstract double eval(double x , double y);
plublic static void main(String[] args){
System.out.println(Operation.PLUS.eval(3,4));
System.out.println(Operation.MINUS.eval(5,4));
}
}
垃圾回收特征:回收堆内存中的对象;在合适的时候进行;先调用它的finallize()方法,可能使该对象复活,导致回收机制取消回收。
只有当对象处于不可达状态时,系统才会真正回收该对象所占有的资源。
强制垃圾回收:知识通知系统,是否回收依然不确定。
finalize()方法:java提供的默认机制来清理该对象的资源。
finalize()方法特点:永远不要主动调用某个对象的finalize()方法;何时调用,是否调用不确定性;JVM执行finalize()方法时,可能使对象重新变成可达状态;JVM执行finalize()方法时出现异常,不会报告,程序继续执行。
Jar文件的全称是Java Archive File,意思是Java档案文件。通常Jar文件是一种压缩文件,与我们常见的ZIP压缩文件兼容,通常也被称为jar包。当然也是有区别的,JAR包中有一个META-INF\MANIFEST.MF文件,当你找成JAR包时,它会自动生成。
当开发了一个应用程序后,这个应用程序包含了很多类,如果需要把这个应用程序提供给别人使用,通常会将这些类文件打包成一个JAR文件,把这个JAR文件提供给别人使用。只要别人在系统的CLASSPATH环境变量中添加这个JAR文件,则Java虚拟机就可以自动在内存中解压这个JAR包,把这个JAR文件当做一个路径,在这个路径中查找所需要的类或包层次对应的路径结构。
JAR命令(简略举例):以文件test创建test.jar
jar cf test.jar test
查看jar文件列表
jar tf test.jar
向test.jar中添加或更新文件
jar vuf test.jar a.txt
将命令执行的过程输出输出到文件a.txt中
jar vtf test.jar > a.txt
将jar中的文件解出到当前目录下
jar xf test.jar a.txt