【java】一些容易忽略的问题

本文深入探讨Java中的访问控制概念,包括不同修饰符的作用范围、抽象类与方法的使用、内部类的访问权限等,并解析final关键字及泛型使用的细节。
1.静态方法中不能调用非静态的成员或成员方法
    不能引用非静态成员变量大家都很清楚:
    public class A
{
    int a;
    public static void main(String[] args)
    {
      a = 2;//错误!!a非静态
    }
}
但是大家往往忽略以下的情况:
package cn.edu.chd.test;
public class B
{
    public static void main(String[] args)
    {
        new C();//错误,该类是动态类
        new B().new C();//正确  
        new D();//正确,该类是静态类
    }
    public void func()
    {
        new C();//正确
        new D();//正确
    }
    class C
    {
    }
    static class D
    {
        
    }
}
C类相当于B类的成员变量,故不能在静态方法中new出实例(记住:类中的静态方法不能直接调用动态方法)。
否则会提示错误:
No enclosing instance of type B is accessible. Must qualify the allocation with an enclosing instance of type B (e.g. x.new A() where x is an instance of B).
2.protected修饰的构造器在包内部可以被new实例,在其他包非子类中不能被new实例。其他包子类可以访问(包括匿名类):
domain包:
package cn.edu.chd.domain;
public class A
{
    protected A(){
        System.out.println("A constructor");
    }
}
test包:
package cn.edu.chd.test;
import cn.edu.chd.domain.A;
public class B
{
    public static void main(String[] args)
    {
    }
    public void func()
    {
        new A();//错误!!!The constructor A() is not visible
        new C();//正确,A的子类可以调A类的protected构造器
      new A(){};//正确,其实这个匿名内部类就相当于new了A的子类  
    }
    class C extends A
    {//C类的无参构造器其实调用了super.A()
    }
}
3.类前面的修饰词只有三种(public/abstract/final),当然内部类除外。
4.访问权限问题:

类中某成员(方法或属性,method or field)的访问权限:

1、package(或称为friendly,但不用写出,friendly也不是关键字)权限,在同一包中的类和继承该类的子类可以访问;

2、public权限,任何类都可以访问;

3、private权限,该类内部的成员(方法、属性、内部类)可以访问,连该类的实例对象都不可以访问;

4、protected权限,继承访问权限,包内其余类和继承该类的子类可以访问,跟friendly权限差不多。

类中构造函数的访问权限:

1、public 很简单,不说了

2、protected 构造函数可以被继承该类的子类调用,但不能在包外或子类以外的地方被调用用来产生实例

3、private 该类无法被继承

内部类的访问权限:

1、public 任何地方均可访问

2、protected 在同一个包内均可访问,不同的包的子类可以访问

3、friendly(即默认权限) 同一个包内才可以访问

4、private 只有该内部类的外部类本身可以访问

类的访问权限:

1、public 任何地方均可访问

2、friendly 即默认权限,又称为package权限,在同一个包内可访问


5.抽象类是以abstract修饰的类,这个类里面可以有抽象的方法也可以没有!!
(1).抽象类不一定有抽象方法,但是有抽象方法的类一定是抽象类。
(2).抽象类不能被实例化!
package cn.edu.chd.demo;
public abstract class Demo
{
//    public abstract void func();//没有抽象方法也叫抽象类,比如HttpServlet类
    public void func1()
    {
        
    } 
}
6.类上声明的泛型只对非静态成员有效
package cn.edu.chd.basic;
public class Demo<T>
{
    public void aa(T t)
    {   
    }
    
    public void bb(T t1,T t2)
    {    
    }
    
//    类上声明的泛型只对非静态成员有效
    public static <T> void cc(T t)
    {
    }
}
7.finally块中代码不执行的一种情况
package  demo;
/**
 *  @author   Rowand   jj
 *这种情况下finally块中代码不执行
 */
public   class  TryDemo
{
     public   static   void  main(String[] args)
    {
         try
        {
            System. out .println( "aaaa" );
            System. exit (1);
        }  catch  (Exception e)
        {
             //  TODO : handle exception
        }
         finally
        {
            System. out .println( "ha" );
        }
    }
}
8.final 修饰的变量,其引用的对象不可以改变,但是我们可以改变对象的内容。
public   class  Deemo
{
     public   static   void  main(String[] args)
    {
         final   Person  p =  new   Person ( "zhangsan" ,11);
        p.setAge(12);//可以
        System. out .println(p.getAge()); 
//        p = new Person(" lisi ",22); //错误
    }
}
class   Person
{
     int   age ;
    String  name ;
    
     public  Person(String name, int  age)
    {
         this . name  = name;
         this . age  = age;
    }
     public   int  getAge()
    {
         return   age ;
    }
     public   void  setAge( int  age)
    {
         this . age  = age;
    }
     public  String getName()
    {
         return   name ;
    }
     public   void  setName(String name)
    {
         this . name  = name;
    }
     }




<think>我们正在处理一个关于Java SocketClient忽略SSL证书验证的问题。根据用户提供的信息,他遇到了"unable to find valid certification path to requested target"错误,并且希望忽略SSL验证。需要注意的是,忽略SSL验证会带来安全风险,因此只建议在测试环境中使用。 在Java中,要忽略SSL证书验证,我们可以通过自定义SSLContext来实现,使用一个信任所有证书的TrustManager。这种方法适用于任何基于SSL/TLS的连接,包括WebSocket和普通的HTTPS连接。 以下是具体的步骤和代码示例: 1. 创建一个自定义的TrustManager,它不会对任何证书进行验证。 2. 初始化一个SSLContext,使用这个自定义的TrustManager。 3. 将SSLContext设置为默认的SSL上下文(可选,影响全局),或者只在你需要的连接中使用。 但是,请注意,用户提到的是使用SocketClient,这里我们假设用户使用的是基于Socket的SSL连接(如SSLSocket)。不过,在WebSocket的情况下,底层也是使用SSL/TLS,因此方法类似。 以下是一个完整的示例代码,展示如何忽略SSL证书验证: ```java import javax.net.ssl.*; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; public class SSLUtil { public static void disableCertificateValidation() { // 创建一个信任所有证书的TrustManager TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; try { // 获取SSLContext实例,并使用自定义的TrustManager初始化 SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new SecureRandom()); // 设置为默认的SSL上下文,这样所有的HttpsURLConnection都会使用 HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); // 设置默认的主机名验证器,忽略主机名验证 HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); } catch (NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } } } ``` 使用方式: 在建立连接之前调用`SSLUtil.disableCertificateValidation()`。这样,后续所有的HTTPS连接(包括WebSocket的wss连接)都会忽略SSL证书验证。 但是,请注意: - 这种方法会全局禁用SSL证书验证,包括主机名验证。因此,它会使你的应用程序容易受到中间人攻击。仅在测试环境中使用。 - 如果你只想针对特定的连接禁用验证,而不是全局,那么你需要为特定的连接设置SSLSocketFactory。例如,对于HttpsURLConnection,你可以这样: ```java URL url = new URL("https://example.com"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(sslContext.getSocketFactory()); conn.setHostnameVerifier((hostname, session) -> true); ``` 对于WebSocket连接,如果你使用的是Java WebSocket API(如Tyrus),你可能需要设置一个自定义的SSLContext。具体方法取决于你使用的WebSocket客户端库。 另外,用户引用了[^1](http://stackoverflow.com/questions/2703161/how-to-ignore-ssl-certificate-errors-in-apache-httpclient-4-0),这个链接是关于Apache HttpClient 4.0忽略SSL证书错误的方法。但用户的问题是关于Java SocketClient的,所以我们没有采用HttpClient的方法。不过,如果用户使用的是HttpClient,那么方法会有所不同。 由于用户的问题是关于SocketClient的,我们提供了上述基于SSLContext的解决方案。 最后,再次强调:在生产环境中,请勿使用忽略证书验证的方法,而应该正确配置信任库,导入服务器证书或信任的CA证书。 相关问题: 1. 如何在Java中为特定的HTTPS连接忽略SSL证书验证? 2. 在Java中,如何将自签名证书导入信任库? 3. 使用Java WebSocket客户端时,如何忽略SSL证书验证?</think>### Java SocketClient 忽略 SSL 证书验证解决方案 当需要在 Java `SocketClient` 中忽略 SSL 证书验证时(**仅限测试环境使用**),可通过自定义 `TrustManager` 实现。以下是完整实现方案: #### 核心代码实现 ```java import javax.net.ssl.*; import java.security.SecureRandom; import java.security.cert.X509Certificate; public class SSLIgnoreUtil { // 创建信任所有证书的 TrustManager private static final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted(X509Certificate[] certs, String authType) { // 空实现 - 信任所有客户端证书 } public void checkServerTrusted(X509Certificate[] certs, String authType) { // 空实现 - 信任所有服务器证书 } } }; // 创建忽略主机名验证的 HostnameVerifier private static final HostnameVerifier trustAllHostnames = (hostname, session) -> true; // 始终返回 true // 获取忽略验证的 SSLContext public static SSLContext createIgnoreSSLContext() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new SecureRandom()); return sslContext; } // 应用全局忽略设置 (慎用!) public static void disableGlobalSSLVerification() throws Exception { SSLContext.setDefault(createIgnoreSSLContext()); HttpsURLConnection.setDefaultHostnameVerifier(trustAllHostnames); } } ``` #### 使用方式 1. **方法一:针对单个连接** ```java // 创建自定义 SSLContext SSLContext sslContext = SSLIgnoreUtil.createIgnoreSSLContext(); // 创建 SSLSocketFactory SSLSocketFactory factory = sslContext.getSocketFactory(); // 建立 SSL 连接 Socket socket = factory.createSocket("example.com", 443); ``` 2. **方法二:全局设置(影响所有连接)** ```java // 应用全局设置(启动时调用一次) SSLIgnoreUtil.disableGlobalSSLVerification(); // 后续所有连接自动忽略验证 Socket socket = SSLSocketFactory.getDefault().createSocket("example.com", 443); ``` #### 注意事项 1. **安全警告** ⚠️ 此方案会**完全禁用 SSL/TLS 证书验证**,使连接暴露于中间人攻击风险中[^1]。仅限以下场景使用: - 测试环境 - 访问受控内网服务 - 临时调试 - **禁止在生产环境使用** 2. 兼容性说明 ```mermaid graph LR A[Java 版本] --> B[Java 6+] A --> C[Java 7+ 推荐] D[协议支持] --> E[TLSv1.2] D --> F[TLSv1.3] ``` 3. 最佳实践 - 优先使用证书导入方案(参考之前回答的 `keytool` 方法) - 为不同服务创建独立 `SSLContext` 实例 - 使用后立即重置默认设置: ```java // 恢复默认验证 SSLContext.setDefault(null); HttpsURLConnection.setDefaultHostnameVerifier(null); ``` #### 替代方案:仅忽略过期证书 ```java // 在 SSLIgnoreUtil 中添加此方法 public static SSLContext createIgnoreExpiredSSLContext() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[] { new X509ExtendedTrustManager() { public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) { // 仅检查证书是否过期 for (X509Certificate cert : chain) { cert.checkValidity(); } } // 其他必要方法实现... } }, new SecureRandom()); return sslContext; } ``` > **关键提示**:即使忽略证书验证,仍建议检查证书有效期以防止过期证书导致的意外中断[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值