Java学习笔记之二
一、 面向对象基础部分
1、this、super
关键字
/**
* @author Administrator
*
* @description 测试基类
* @history
*/
public class BaseTest {
protected String pwd; // 定义protected属性pwd
public BaseTest(){
// 无参数构造方法
}
public String sayHelloWorld(){
return "hello world";
}
}
/**
* @author Administrator
*
* @description this,super关键字测试类
* @history
*/
public class MyTestDemo extends BaseTest{
// notes:测试使用而已,代码功能模拟而已
private String username; // 定义用户昵称私有属性private修饰
private String password;
public MyTestDemo(String username){ // 构造方法
this();// this()调用无参数构造方法
this.username = username; // this.属性访问当前username属性
// super.属性调用父类属性
this.password = super.pwd;
}
public MyTestDemo(){
// 无参数构造方法
super(); // 调用父类无参数构造方法
}
public void sayHello(){
this.sayWord(); // this.方法调用当前对象的sayWord方法
super.sayHelloWorld(); // super.方法调用父类sayHelloWorld方法
}
public String sayWord(){
return "hello this";
}
// this表示当前对象
public boolean equals(Object obj){
MyTestDemo other = (MyTestDemo)obj; // 传入的比较对象,强制转换操作
// 简单模拟,如果对象的username属性值相同那么就认为相同
if(this == other){
return true;
}
if(other instanceof MyTestDemo){
if(this.username.equals(other.username)){
return true;
}
}
return false;
}
/**
*@description
*@param args
*/
public static void main(String[] args) {
// this关键字绑定了当前该对象,通过this.属性、this.方法
// super关键字用在子类要调用父类的属性或者方法中,通过super.属性、super.方法
MyTestDemo obj1 = new MyTestDemo("hello-java"); // 定义并实例化对象
obj1.sayHello(); // 调用对象的sayHello方法
MyTestDemo obj2 = new MyTestDemo("hello-java");
// equals方法传入的参数类型为object,传入的obj2会自动向上转型处理
boolean result = obj1.equals(obj2);
System.out.println(result); // true
}
}
2、static、final关键字
/**
* @author Administrator
*
* @description final和static关键字学习
* @history
*/
public class FinalAndStaticTestDemo {
/**
*@description
*@param args
*/
public static void main(String[] args) {
// final关键字主要有三种场景
// 1、final定义的变量为常量,比如基本数据类型的值一旦初始化了不能改变
// 2、final定义的类为终结类,不能再被继承,比如string类型
// 3、final定义的方法为终结方法,不能被覆写,否则编译器会报错
final String str = "helloworld"; // final修饰变为常量不能改变
//str = "hellojava"; // eclipse提示:The final local variable str cannot be assigned.
// 进一步思考下面两个问题
String s1 = "hello";
String s2 = "hello1";
final String s = s1;
s1 = s2;
System.out.println(s); // hello还是hello1呢?
// 引用不可变,内容可变是这个意思吗?
StringBuffer sb = new StringBuffer();
sb.append("hello");
final String fs = sb.toString();
final StringBuffer fsb = sb;
sb.append("world");
System.out.println(fs);// hello还是helloworld呢?
System.out.println(fsb.toString()); // hello还是helloworld呢?
// static关键字比较类似也有下面三种场景
// static修饰的变量为静态变量,它不同于对象/实例变量,是关联在某个类上的
// static修饰的类为静态类
// static修饰的方法为静态方法,它也不同于对象/实例方法,是关联在某个类上的
// static int i = 100;
// static class HelloWorld{ //... }
// public static void sayHeloWorld(){ //... }
}
// 静态变量和对象变量
static int i = 100; // 定义静态变量i
int j = 100; // 定义成员变量/实例变量
public static void sayHelloWorld(){ // 定义静态方法sayhelloworld
System.out.println("hello world");
}
static class HelloWorld{ // 定义内部类
// ...
}
}
3、引用传递介绍和应用
/**
* @author Administrator
*
* @description 引用传递的简单学习
* @history
*/
class DemoTest{
String ide = "eclipse"; // 为了方便访问暂不封装
}
public class MyDemoTest{
/**
*@description
*@param args
*/
public static void main(String[] args){
// 对象属性值访问和变更
DemoTest dt1 = new DemoTest();
System.out.println(dt1.ide); // eclipse
dt1.ide = "netbeans"; // 改变ide属性值
System.out.println(dt1.ide); // netbeans
function(dt1); // 调用方法function
System.out.println(dt1.ide); // jcreator
// String类赋值和变更
String ide = "eclipse";
function(ide);
System.out.println(ide); // eclipse而不是netbeans
}
private static void function(String ide) {
ide = "netbeans"; // 赋值为netbeans
}
// 测试方法function
private static void function(DemoTest dt2) {
dt2.ide = "jcreator"; // 改变ide属性值
}
}
4、静态块、代码块、
同步块
/**
* @author Administrator
*
* @description 静态块、代码块、同步块学习测试类
* @history
*/
class BlockDemo {
static {
// 在类中定义的static{ //...}为静态代码块
// 静态代码块的程序只会被初始化一次
System.out.println("BlockDemo->static");
}
{
// 在类中定义的{ //...}为构造代码块
// 构造代码块和对象一起初始化的
System.out.println("BlockDemo->{}");
}
public BlockDemo() {
System.out.println("BlockDemo->BlockDemo");
}
// 构造方法、构造代码块和静态代码块初始化顺序呢?
// 静态块、构造块、构造方法 // 表面初步分析,具体有待研究
}
public class MyDemo {
/**
* @description
* @param args
*/
public static void main(String[] args) {
// 静态块、代码块、同步块
{
// 在方法中用{ //... }定义的为普通代码块
int x = 100;
System.out.println(x); // 100 相当于局部变量
}
int x = 200;
System.out.println(x); // 200
new BlockDemo();
new BlockDemo();
// BlockDemo->static static代码块只会被初始化一次
// BlockDemo->{}
// BlockDemo->BlockDemo
// BlockDemo->{}
// BlockDemo->BlockDemo
}
}
5、构造方法、匿名对象、单例定义以及实现
/**
* @author Administrator
*
* @description 构造方法、匿名对象学习测试类
* @history
*/
public class MyDemoTest {
private String username; // 定义私有属性username
// 构造方法的作用是初始化操作
// 构造方法是一种特殊的方法,构造方法也有重载
public MyDemoTest(){
// 无参数构造方法
}
public MyDemoTest(String username) { // 定义构造方法
this.username = username; // 对属性初始化赋值操作
}
/**
*@description
*@param args
*/
public static void main(String[] args) {
// 实例化一个匿名对象
// 匿名对象不在栈中开辟空间赋地址值
new MyDemoTest("eclipse");
}
}
/**
* @author Administrator
*
* @description 单例学习测试类
* @history
*/
class Singleton {
private Singleton() {
// 将构造方法私有化,外部不能直接调用
System.out.println("private Singleton(){//...}");
}
// 饿汉式获取单例代码
private static Singleton instance = new Singleton();
// 对外提供一个getInstance方法获取单例
public static Singleton getIntance() {
return instance;
}
}
class Singleton2{
private Singleton2(){
// 构造方法私有化,外部不能直接调用
System.out.println("private Singleton2(){//...}");
}
// 懒汉式获取单例代码
private static Singleton2 instance = null;
private static Object lock = new Object();
// 获取单例方法,效率比较低
// 每次进入都要进行锁判断,而实际情况我们是第一次null比较特殊
/*public static Singleton2 getIntance(){
synchronized (lock) {
if (instance == null) { // 如果为null进行实例化对象操作
instance = new Singleton2();
}
}
return instance;
}*/
// 上面同步代码的另外一种写法如下,效率比较低
// public static synchronized getInstance(){ //...}
// 对同步代码进行改写
public static Singleton2 getIntance(){
if(instance == null){
synchronized(lock){
if(instance == null){ // 进行双重检验操作
instance = new Singleton2();
}
}
// 如果换为下面这种形式那么就可能不是产生一个实例对象了
/*synchronized(lock){
instance = new Singleton2();
}*/
}
return instance;
}
}
public class SingletonTest {
/**
*@description
*@param args
*/
public static void main(String[] args) {
Singleton.getIntance(); // 饿汉式获取单例
Singleton2.getIntance(); // 懒汉式获取单例
}
}
6、内部类、匿名内部类应用
class Outer{ // 定义外部类
private String info = "helloworld" ; // 定义外部类属性
private static String info2 = "helloeclipse"; // 定义静态变量
class Inner{ // 定义内部类
public void print(){
// 内部类的好处之一:直接访问外部类属性
System.out.println(info) ; // 直接访问外部类属性
}
}
static class StaticInner{ // 通过static定义的内部类为外部类
public void print(){
System.out.println(info2);
}
}
public void fun(){
new Inner().print() ; // 通过内部类的实例化对象调用方法
}
}
/**
* @author Administrator
*
* @description 内部类以及匿名内部类学习测试类
* @history
*/
public class InnerClassDemo{
/**
*@description
*@param args
*/
public static void main(String[] args){
new Outer().fun() ; // 调用外部类的fun()方法
// 另外一种实例化方式
Outer out = new Outer();
Outer.Inner in = out.new Inner();
in.print();
// 通过外部类.内部类实例化内部类对象
//StaticInner sin = new Outer.StaticInner(); //需要导入外部类所在的包
//sin.print();
}
}
二、 面向对象高级部分
1、继承的进一步讨论
class Base{
// 定义基类
void print(){
System.out.println("Base->print()");
}
public void print1(){
// 父类方法的访问权限,子类覆写该方法的时候不能降低权限
}
}
class ZiLei extends Base{
// 定义子类覆写print方法
void print(){
// 子类访问父类中的方法,前面super关键字内容
// super.print();
System.out.println("Super->print()");
}
/*void print1(){
// Cannot reduce the visibility of the inherited method from Base
}*/
// 覆写override和重载overload区别
// 覆写是父类子类之间的关系,重载是同一个类之间的关系
}
/**
* @author Administrator
*
* @description 继承中的方法覆写
* @history
*/
public class OverrideDemo{
public static void main(String args[]){
new ZiLei().print(); // 调用的内容是覆写后的方法实现
// 另外java中只能够单继承,不同于C++,但是可以多重继承
/*class A{
// ...
}
class B extends A{ //class C extends A,B{ // ...}编译错误
// ...
}
class C extends B{
// ...
}*/
}
}
2、
接口和抽象类进一步讨论
/**
* @author Administrator
*
* @description 接口测试类
* @history
*/
interface Interface{
public static final String INFO = "helloeclipse";
public void print(); // 定义方法
public abstract void printInfo();
}
class I implements Interface{
public void print() {
// 方法实现
System.out.println(INFO); // helloeclipse
}
public void printInfo() {
// ...
}
}
public class InterfaceTestDemo {
/**
*@description
*@param args
*/
public static void main(String[] args) {
// 接口interface
// 接口interface和抽象类abstract一样不能直接实例化必须通过子类来实现
new Interface(){
public void print() {
// 匿名内部类,方法实现
System.out.println(INFO); // helloeclipse
}
public void printInfo() {
// ...
}
};
// 接口和抽象类对比,接口更像一种规范、抽象类更像一种模板
// 抽象类定义一些公共的实现,以及一些未实现的方法交给子类具体实现特定的功能-模板方法
}
}
/**
* @author Administrator
*
* @description 抽象类学习测试类
* @history
*/
abstract class Abstract{ // 定义抽象类
public final static String INFO = "helloeclipse"; // 定义全局变量/常量
abstract public void print(); // 定义抽象方法
// 抽象类不能直接实例化,抽象类的子类如果不是抽象类那么一定要实现所有的抽象方法
}
class AbstractZiLei extends Abstract{ // 定义抽象子类
public void print() { // 实现子类方法
System.out.println(INFO);
}
}
public class AbstractTestDemo {
/**
*@description
*@param args
*/
public static void main(String[] args) {
// 接口和抽象类interface,abstract
// 抽象类:含有抽象方法的类叫做抽象类用abstract修饰的
new Abstract(){
public void print() {
System.out.println(INFO); // 匿名抽象类实现
}
};
// 抽象类能不能被final修饰呢?final定义的类为终结类,抽象类是需要子类来实现的
// final abstract class Abstract{ //... } // 编译报错
}
}
3、object类和包装类进一步讨论
/**
* @author Administrator
*
* @description Object类学习测试类
* @history
*/
public class ObjectTestDemo {
/**
*@description
*@param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
// Object类学习测试代码
// 1、toString方法
// 2、equals和hashCode方法
// 3、getClass方法
ObjectTestDemo otd = new ObjectTestDemo();
System.out.println(otd);
System.out.println(otd.toString());// 现实调用toString方法
/*
* Object类中toString方法
* public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
* Object类中equal方法
* public boolean equals(Object obj) {
return (this == obj);
}*/
// 定义昵称和年龄属性,如果昵称和年龄相同则equal方法返回true
ObjectTestDemo otd1 = new ObjectTestDemo();
otd1.nickname = "eclipse";
otd1.age = 20;
ObjectTestDemo otd2 = new ObjectTestDemo();
otd2.nickname = "eclipse";
otd2.age = 20;
System.out.println(otd1==otd2); // false
System.out.println(otd1.equals(otd2)); // 如果不覆写的话返回的一直是false
// hashCode方法和equals方法的关系,没有绝对的关系
// 具体参看源代码的注释说明,在实际用中尽量同时覆写这两个方法,保持一致性
// public final native Class<?> getClass();
// getClass方法是一个本地方法,调用底层代码,返回当前对象对应的一个类对象实例
// 类对象实例,理解为内存中对应的那份字节码对象,java反射内容初步学习
// 通过字节码对象构造出一个个的对象实例
Class claz = otd.getClass();
Class claz1 = ObjectTestDemo.class;
Class claz2 = Class.forName("ObjectTestDemo"); // 类的完整路径
System.out.println(otd.getClass()); // class ObjectTestDemo
// VM内存中只会产生一份字节码对象
System.out.println(claz == claz1); // true
}
// 方法模拟,添加两个属性昵称和年龄
private String nickname;
private int age;
// 注意参数类型不要写成了ObjectTestDemo
public boolean equals(Object obj) {
ObjectTestDemo otd = (ObjectTestDemo) obj; // 向上转型,强制转换
if (this == otd) {
return true;
}
if (otd instanceof ObjectTestDemo) {
if (this.nickname.equals(otd.nickname) && this.age == otd.age) {
return true;
}
}
return false;
}
public String toString(){
return "helloworld"; //覆写toString方法,返回helloworld
}
}